<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge" >
  <link rel="dns-prefetch" href="http://example.com">
  <title>Hexo博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="兴趣程序猿的个人博客">
<meta property="og:type" content="website">
<meta property="og:title" content="Hexo博客">
<meta property="og:url" content="http://example.com/index.html">
<meta property="og:site_name" content="Hexo博客">
<meta property="og:description" content="兴趣程序猿的个人博客">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="忒休斯的Code">
<meta property="article:tag" content="技术  日常">
<meta name="twitter:card" content="summary">
  
    <link rel="alternative" href="/atom.xml" title="Hexo博客" type="application/atom+xml">
  
  
    <link rel="icon" href="/img/learning.jpg">
  
  <link rel="stylesheet" type="text/css" href="/./main.0cf68a.css">
  <style type="text/css">
  
    #container.show {
      background: linear-gradient(200deg,#ccc,#000);
    }
  </style>
  

  

<meta name="generator" content="Hexo 5.2.0"></head>

<body>
  <div id="container" q-class="show:isCtnShow">
    <canvas id="anm-canvas" class="anm-canvas"></canvas>
    <div class="left-col" q-class="show:isShow">
      
<div class="overlay" style="background: #4d4d4d"></div>
<div class="intrude-less">
	<header id="header" class="inner">
		<a href="/" class="profilepic">
			<img src="/assets/fighting.png" class="js-avatar">
		</a>
		<hgroup>
		  <h1 class="header-author"><a href="/"></a></h1>
		</hgroup>
		

		<nav class="header-menu">
			<ul>
			
				<li><a href="/">主页</a></li>
	        
				<li><a href="/tags/%E9%9A%8F%E7%AC%94/">随笔</a></li>
	        
			</ul>
		</nav>
		<nav class="header-smart-menu">
    		
    			
    			<a q-on="click: openSlider(e, 'innerArchive')" href="javascript:void(0)">所有文章</a>
    			
            
    			
    			<a q-on="click: openSlider(e, 'friends')" href="javascript:void(0)">友链</a>
    			
            
    			
    			<a q-on="click: openSlider(e, 'aboutme')" href="javascript:void(0)">关于我</a>
    			
            
		</nav>
		<nav class="header-nav">
			<div class="social">
				
					<a class="github" target="_blank" href="https://gitee.com/chinese_fb/projects" title="github"><i class="icon-github"></i></a>
		        
					<a class="weibo" target="_blank" href="#" title="weibo"><i class="icon-weibo"></i></a>
		        
					<a class="bilibili" target="_blank" href="https://space.bilibili.com/66423607" title="bilibili"><i class="icon-bilibili"></i></a>
		        
					<a class="zhihu" target="_blank" href="#" title="zhihu"><i class="icon-zhihu"></i></a>
		        
			</div>
			
			<!-- 网易云音乐插件 -->
			
				 <div style="position:absolute; bottom:120px left:auto; width:85%">
					<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=270 height=86 src="//music.163.com/outchain/player?type=2&id=5271858&auto=1&height=66"></iframe>
				</div>
			
		</nav>
	</header>		
</div>

    </div>
    <div class="mid-col" q-class="show:isShow,hide:isShow|isFalse">
      
<nav id="mobile-nav">
  	<div class="overlay js-overlay" style="background: #4d4d4d"></div>
	<div class="btnctn js-mobile-btnctn">
  		<div class="slider-trigger list" q-on="click: openSlider(e)"><i class="icon icon-sort"></i></div>
	</div>
	<div class="intrude-less">
		<header id="header" class="inner">
			<div class="profilepic">
				<img src="/assets/fighting.png" class="js-avatar">
			</div>
			<hgroup>
			  <h1 class="header-author js-header-author"></h1>
			</hgroup>
			
			
			
				
			
				
			
			
			
			<nav class="header-nav">
				<div class="social">
					
						<a class="github" target="_blank" href="https://gitee.com/chinese_fb/projects" title="github"><i class="icon-github"></i></a>
			        
						<a class="weibo" target="_blank" href="#" title="weibo"><i class="icon-weibo"></i></a>
			        
						<a class="bilibili" target="_blank" href="https://space.bilibili.com/66423607" title="bilibili"><i class="icon-bilibili"></i></a>
			        
						<a class="zhihu" target="_blank" href="#" title="zhihu"><i class="icon-zhihu"></i></a>
			        
				</div>
			</nav>

			<nav class="header-menu js-header-menu">
				<ul style="width: 50%">
				
				
					<li style="width: 50%"><a href="/">主页</a></li>
		        
					<li style="width: 50%"><a href="/tags/%E9%9A%8F%E7%AC%94/">随笔</a></li>
		        
				</ul>
			</nav>
		</header>				
	</div>
	<div class="mobile-mask" style="display:none" q-show="isShow"></div>
</nav>

      <div id="wrapper" class="body-wrap">
        <div class="menu-l">
          <div class="canvas-wrap">
            <canvas data-colors="#eaeaea" data-sectionHeight="100" data-contentId="js-content" id="myCanvas1" class="anm-canvas"></canvas>
          </div>
          <div id="js-content" class="content-ll">
            
  
    <article id="post-MySQL面试笔记" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/06/08/MySQL%E9%9D%A2%E8%AF%95%E7%AC%94%E8%AE%B0/">MySQL面试笔记</a>
    </h1>
  

        
        <a href="/2021/06/08/MySQL%E9%9D%A2%E8%AF%95%E7%AC%94%E8%AE%B0/" class="archive-article-date">
  	<time datetime="2021-06-08T14:31:09.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-06-08</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="一、100道MySQL常见面试题总结"><a href="#一、100道MySQL常见面试题总结" class="headerlink" title="一、100道MySQL常见面试题总结"></a>一、100道MySQL常见面试题总结</h1><blockquote>
<p>此文不会事无巨细的从select的用法开始讲解mysql,主要针对的是开发人员需要知道的一些<strong>MySQL的知识点</strong>,主要包括索引,事务,优化等方面,以在面试中高频的问句形式给出答案.</p>
</blockquote>
<h2 id="索引相关"><a href="#索引相关" class="headerlink" title="索引相关"></a><strong>索引相关</strong></h2><p>关于MySQL的索引,曾经进行过一次总结,文章链接在这里 Mysql索引原理及其优化.</p>
<p><strong>1. 什么是索引?</strong></p>
<blockquote>
<p><strong>索引是一种数据结构</strong>,可以帮助我们快速的进行数据的查找.</p>
</blockquote>
<p><strong>2. 索引是个什么样的数据结构呢?</strong></p>
<blockquote>
<p>索引的数据结构<strong>和具体存储引擎的实现有关</strong>。在MySQL中使用较多的索引有<strong>Hash索引,B+树索引</strong>等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引。</p>
</blockquote>
<p><strong>3. Hash索引和B+树所有有什么区别或者说优劣呢?</strong></p>
<blockquote>
<p>首先要知道Hash索引和B+树索引的底层实现原理:</p>
<p>​     <strong>hash索引底层就是hash表</strong>,进行查找时,<strong>调用一次hash函数就可以获取到相应的键值</strong>,之后进行回表查询获得实际数据.</p>
<p>​    <strong>B+树底层实现是多路平衡查找树</strong>.对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据。</p>
</blockquote>
<p>那么可以看出他们有以下的不同:</p>
<blockquote>
<ul>
<li>hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询.</li>
</ul>
<blockquote>
<p>因为在hash索引中<strong>经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询</strong>.而B+树的的<strong>所有节点皆遵循(左节点小于父节点,右节点大于父节点</strong>,多叉树也类似),天然支持范围。</p>
</blockquote>
<ul>
<li><strong>hash索引不支持使用索引进行排序</strong>,原理同上.</li>
<li><strong>hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测</strong>。<strong>AAAA</strong>和<strong>AAAAB</strong>的索引没有相关性。</li>
<li>hash索引<strong>任何时候都避免不了回表查询数据</strong>，而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询.</li>
<li><strong>hash索引虽然在等值查询上较快,但是不稳定</strong>.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而<strong>B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低</strong>.</li>
</ul>
</blockquote>
<p>因此,在大多数情况下,<strong>直接选择B+树索引可以获得稳定且较好的查询速度.而不需要使用hash索引</strong>.</p>
<p><strong>4. 上面提到了B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引?</strong></p>
<blockquote>
<p>在B+树的索引中,叶子节点<strong>可能存储了当前的key值,也可能存储了当前的key值以及整行的数据</strong>,这就是聚簇索引和非聚簇索引。</p>
</blockquote>
<blockquote>
<h3 id="聚簇索引-聚集索引-叶子节点存储数据"><a href="#聚簇索引-聚集索引-叶子节点存储数据" class="headerlink" title="聚簇索引(聚集索引):叶子节点存储数据"></a>聚簇索引(聚集索引):叶子节点存储数据</h3><p>　　聚簇索引就是按照每张表的主键构造一颗B+树，同时叶子节点中存放的就是整张表的行记录数据，也将聚集索引的叶子节点称为数据页。这个特性决定了索引组织表中数据也是索引的一部分，每张表只能拥有一个聚簇索引。</p>
<h3 id="辅助索引-非聚簇索引-叶子节点存储的是主键值。"><a href="#辅助索引-非聚簇索引-叶子节点存储的是主键值。" class="headerlink" title="辅助索引(非聚簇索引):叶子节点存储的是主键值。"></a>辅助索引(非聚簇索引):叶子节点存储的是主键值。</h3><p>　　在<strong>聚簇索引之上创建的索引称之为辅助索引</strong>，辅助索引访问数据<strong>总是需要二次查找</strong>。辅助索引叶子节点存储的不再是行的物理位置，而是主键值。通过辅助索引首先找到的是主键值，再通过主键值找到数据行的数据页，再通过数据页中的Page Directory找到数据行。</p>
</blockquote>
<p><strong>建立聚簇索引的顺序：主键索引→唯一键→隐式生成键</strong></p>
<blockquote>
<p>在InnoDB中,<strong>只有主键索引是聚簇索引</strong>；如果没有主键,则挑选一个唯一键建立聚簇索引.如果没有唯一键,则隐式的生成一个键来建立聚簇索引.</p>
</blockquote>
<p>当查询使用聚簇索引时,<strong>在对应的叶子节点,可以获取到整行数据</strong>,因此不用再次进行回表查询.</p>
<p><strong>5. 非聚簇索引一定会回表查询吗?</strong></p>
<p>不一定。这涉及到<strong>查询语句所要求的字段是否全部命中了索引</strong>,如果全部命中了索引,那么就不必再进行回表查询.</p>
<p>举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age &lt; 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询.</p>
<p><strong>6. 在建立索引的时候,都有哪些需要考虑的因素呢?</strong></p>
<blockquote>
<p>建立索引的时候<strong>一般要考虑到字段的使用频率</strong>,经常作为条件进行查询的字段比较适合.</p>
<p>如果需要<strong>建立联合索引的话,还需要考虑联合索引中的顺序</strong>.此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力.这些都和实际的表结构以及查询方式有关.</p>
</blockquote>
<p><strong>7. 联合索引是什么?为什么需要注意联合索引中的顺序?</strong></p>
<p>MySQL可以<strong>使用多个字段同时建立一个索引,叫做联合索引</strong>.在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引.</p>
<p>具体原因为:</p>
<blockquote>
<p>​      MySQL使用索引时需要索引有序,假设现在建立了”name,age,school”的联合索引,那么索引的排序为: <strong>先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序.</strong></p>
<p>​      当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找。以此类推.因此在建立联合索引的时候应该注意索引列的顺序,<strong>一般情况下,将查询需求频繁或者字段选择性高的列放在前面</strong>。此外可以根据特例的查询或者表结构进行单独的调整.</p>
</blockquote>
<p><strong>8. 创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?</strong></p>
<p>​    <strong>MySQL提供了explain命令来查看语句的执行计划</strong>。MySQL在执行某个语句之前,会将该语句过一遍查询优化器,之后会拿到对语句的分析,也就是执行计划,其中包含了许多信息. 可以通过其中和索引有关的信息来分析是否命中了索引,例如possilbe_key,key,key_len等字段,分别说明了此语句可能会使用的索引,实际使用的索引以及使用的索引长度.</p>
<p><strong>9. 那么在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?</strong></p>
<blockquote>
<ul>
<li>使用不等于查询,</li>
<li>列参与了数学运算或者函数</li>
<li>在<strong>字符串like时左边是通配符</strong>.类似于’%aaa’.</li>
<li>当mysql分析全表扫描比使用索引快的时候不使用索引.</li>
<li><strong>当使用联合索引,前面一个条件为范围查询</strong>,后面的即使符合最左前缀原则,也无法使用索引.</li>
</ul>
<p>以上情况,MySQL无法使用索引.</p>
</blockquote>
<h2 id="事务相关"><a href="#事务相关" class="headerlink" title="事务相关"></a><strong>事务相关</strong></h2><p><strong>1. 什么是事务?</strong></p>
<p>理解什么是事务最经典的就是转账的例子。</p>
<p><strong>事务是一系列的操作,他们同时要符合ACID特性</strong>.</p>
<p>**2. ACID是什么?可以详细说一下吗?**（原子性、持久性、隔离性、一致性）</p>
<blockquote>
<p>即要求一个事务的操作过程必须要么成功，要么失败；在操作过程中，对其他事务不可见（确保安全）；操作以后的结果是确定（不存在中间状态）、且持久的。</p>
</blockquote>
<blockquote>
<p>A=Atomicity</p>
<p>原子性,就是上面说的,要么全部成功,要么全部失败.<strong>不可能只执行一部分操作</strong>.</p>
<p>C=Consistency</p>
<p>一致性，系统(数据库)总是从一个一致性的状态转移到另一个一致性的状态,<strong>不会存在中间状态</strong>.</p>
<p>I=Isolation</p>
<p>隔离性: 通常来说:一个事务<strong>在完全提交之前,对其他事务是不可见</strong>的.注意前面的通常来说加了红色,意味着有例外情况.</p>
<p>D=Durability</p>
<p>持久性,<strong>一旦事务提交,那么就永远是这样子了</strong>,哪怕系统崩溃也不会影响到这个事务的结果.</p>
</blockquote>
<p><strong>3. 同时有多个事务在进行会怎么样呢?</strong></p>
<p>多事务的并发进行一般会造成以下几个问题:<strong>（脏  幻  不可重复）读</strong></p>
<blockquote>
<ul>
<li>脏读: <strong>A事务读取到了B事务未提交的内容,而B事务后面进行了回滚.</strong></li>
<li>不可重复读: 当设置A事务只能读取B事务已经提交的部分,会造成在A事务内的两次查询,结果竟然不一样,因为在此期间B事务进行了提交操作. (<strong>A事务对B事物进行了部分提交、操作全部提交两种情况下的查询结果不同。</strong>)</li>
<li>幻读: A事务读取了一个范围的内容,而同时B事务在此期间插入了一条数据.造成”幻觉”. （<strong>读取过程中，发生了添加等操作。</strong>）</li>
</ul>
</blockquote>
<p><strong>4. 怎么解决这些问题呢?MySQL的事务隔离级别了解吗?</strong></p>
<p>MySQL的四种隔离级别如下:</p>
<blockquote>
<ul>
<li>未提交读(READ UNCOMMITTED)   →    由于过程中可读，<strong>易造成脏读</strong>。</li>
</ul>
<blockquote>
<p>这就是上面所说的例外情况了,这个隔离级别下,<strong>其他事务可以看到本事务没有提交的部分修改</strong>.因此会造成脏读的问题(读取到了其他事务未提交的部分,而之后该事务进行了回滚).</p>
<p>这个级别的性能没有足够大的优势,但是又有很多的问题,<strong>因此很少使用</strong>.</p>
</blockquote>
<ul>
<li>已提交读(READ COMMITTED)    →   由于只以提交结果为准，当结果不同时，<strong>会发生不可重复读问题</strong>。</li>
</ul>
<blockquote>
<p>其他事务只能读取到本事务已经提交的部分.这个隔离级别有 不可重复读的问题,在同一个事务内的两次读取,拿到的结果竟然不一样,因为另外一个事务对数据进行了修改.</p>
</blockquote>
<ul>
<li>REPEATABLE READ(可重复读)  →   由于采用了读锁，但未阻止插入等问题，因此<strong>会造成幻读(之前的数据没变，但有新增)问题</strong>。</li>
</ul>
<blockquote>
<p>可重复读隔离级别解决了上面不可重复读的问题(看名字也知道),但是仍然有一个新问题,就是 幻读,当你读取id&gt; 10 的数据行时,对涉及到的所有行加上了读锁,此时例外一个事务新插入了一条id=11的数据,因为是新插入的,所以不会触发上面的锁的排斥,那么进行本事务进行下一次的查询时会发现有一条id=11的数据,而上次的查询操作并没有获取到,再进行插入就会有主键冲突的问题.</p>
</blockquote>
<ul>
<li>SERIALIZABLE(可串行化)</li>
</ul>
<p><strong>这是最高的隔离级别</strong>,<strong>可以解决上面提到的所有问题</strong>。因为他强制将所以的操作串行执行,这会导致并发性能极速下降,<strong>因此也不是很常用.</strong></p>
</blockquote>
<p><strong>5. Innodb使用的是哪种隔离级别呢?</strong></p>
<blockquote>
<p>InnoDB默认使用的是<strong>可重复读隔离级别</strong>.</p>
</blockquote>
<p><strong>6. 对MySQL的锁了解吗?</strong></p>
<p><strong>当数据库有并发事务的时候,可能会产生数据的不一致</strong>,这时候需要一些机制来保证访问的次序,<strong>锁机制就是这样的一个机制</strong>.</p>
<p>就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用.</p>
<p><strong>7. MySQL都有哪些锁呢?像上面那样子进行锁定岂不是有点阻碍并发效率了?</strong></p>
<p>从锁的类别上来讲,有共享锁和排他锁. (共享锁可以有多个，确保读取数据一致；排它锁只有一个，确保数据写入准确。)</p>
<blockquote>
<p>共享锁: 又叫做读锁. <strong>当用户要进行数据的读取时,对数据加上共享锁.共享锁可以同时加上多个</strong>.</p>
<p>排他锁: 又叫做写锁. 当用户要<strong>进行数据的写入时,对数据加上排他锁</strong>.排他锁只可以加一个,他和其他的排他锁,共享锁都相斥.</p>
</blockquote>
<blockquote>
<p>解释：用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的. 一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以。</p>
</blockquote>
<p><strong>锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁</strong>.</p>
<p>他们的加锁开销从大到小,并发能力也是从大到小.</p>
<h2 id="表结构设计"><a href="#表结构设计" class="headerlink" title="表结构设计"></a><strong>表结构设计</strong></h2><p><strong>1. 为什么要尽量设定一个主键?</strong></p>
<p><strong>主键是数据库确保数据行在整张表唯一性的保障</strong>。</p>
<p><strong>即使业务上本张表没有主键,也建议添加一个自增长的ID列作为主键</strong>.设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全.</p>
<p><strong>2. 主键使用自增ID还是UUID?</strong></p>
<p>**推荐使用自增ID,**不要使用UUID.</p>
<blockquote>
<p>因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的。也就是说,<strong>主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可</strong>；</p>
<p>如果是UUID,由于到来的ID与原来的<strong>大小不确定,会造成非常多的数据插入</strong>,数据移动,然后导致产生很多的内存碎片,<strong>进而造成插入性能的下降</strong>。</p>
</blockquote>
<p>总之,在<strong>数据量大一些的情况下,用自增主键性能会好一些</strong>.</p>
<p><strong>3. 字段为什么要求定义为not null?</strong></p>
<blockquote>
<p><strong>null值会占用更多的字节,且会在程序中造成很多与预期不符的情况.</strong></p>
</blockquote>
<p><strong>4. 如果要存储用户的密码散列,应该使用什么字段进行存储?</strong></p>
<p>密码散列,盐,用户身份证号<strong>等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率</strong>.</p>
<h2 id="存储引擎相关"><a href="#存储引擎相关" class="headerlink" title="存储引擎相关"></a><strong>存储引擎相关</strong></h2><p><strong>1. MySQL支持哪些存储引擎?</strong></p>
<p>MySQL支持多种存储引擎,比如<strong>InnoDB,MyISAM,Memory,Archive</strong>等等.</p>
<p>在大多数的情况下,直接选择使用InnoDB引擎都是最合适的,<strong>InnoDB也是MySQL的默认存储引擎.</strong></p>
<ol>
<li><p>*<em>InnoDB和MyISAM有什么区别?****</em></p>
<table>
<thead>
<tr>
<th></th>
<th>InnoDB</th>
<th>MyISAM</th>
</tr>
</thead>
<tbody><tr>
<td>事务</td>
<td>支持</td>
<td>不支持</td>
</tr>
<tr>
<td>锁的级别</td>
<td>支持行级锁</td>
<td>支持表级锁</td>
</tr>
<tr>
<td>MVCC</td>
<td>支持</td>
<td>不支持</td>
</tr>
<tr>
<td>外键</td>
<td>支持</td>
<td>不支持</td>
</tr>
<tr>
<td>全文索引</td>
<td>不支持</td>
<td>支持</td>
</tr>
</tbody></table>
</li>
</ol>
<h2 id="零散问题"><a href="#零散问题" class="headerlink" title="零散问题"></a><strong>零散问题</strong></h2><p><strong>1. MySQL中的varchar和char有什么区别.</strong></p>
<blockquote>
<p><strong>char是一个定长字段</strong>,假如申请了char(10)的空间,那么<strong>无论实际存储多少内容.该字段都占用10个字符</strong>,</p>
<p>而varchar是变长的,也就是说申请的只是最大长度,<strong>占用的空间为实际字符长度+1</strong>,最后一个字符存储使用了多长的空间.</p>
</blockquote>
<p><strong>在检索效率上来讲,char &gt; varchar</strong>.   (确定某字段长度，尽量使用char;如MD5加密后的密码、手机号等)</p>
<p>因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar.例如存储用户MD5加密后的密码,则应该使用char.</p>
<p><strong>2. varchar(10)和int(10)代表什么含义?</strong>     (申请的空间长度为10  /   将结果按照10位进行展示。)</p>
<blockquote>
<p><strong>varchar的10代表了申请的空间长度</strong>,也是可以存储的数据的最大长度,</p>
<p>而<strong>int的10只是代表了展示的长度,不足10位以0填充</strong>.也就是说,int(1)和int(10)所能存储的数字大小以及占用的空间都是相同的,<strong>只是在展示时按照长度展示.</strong></p>
</blockquote>
<p><strong>3. MySQL的binlog有几种录入格式?分别有什么区别?</strong></p>
<p>有三种格式,statement,row和mixed.</p>
<blockquote>
<ul>
<li><strong>statement模式下,记录单元为语句.即每一个sql造成的影响会记录</strong>.由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制.</li>
<li><strong>row级别下,记录单元为每一行的改动</strong>,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大.</li>
<li>mixed. 一种折中的方案,<strong>普通操作使用statement记录,当无法使用statement的时候使用row</strong>.</li>
</ul>
</blockquote>
<p>此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录.</p>
<p><strong>4. 超大分页怎么处理?</strong></p>
<p>超大的分页一般从两个方向上来解决.</p>
<ul>
<li><p>数据库层面,这也是我们主要集中关注的(虽然收效没那么大),类似于select * from table where age &gt; 20 limit 1000000,10这种查询其实也是有可以优化的余地的. </p>
<p>这条语句需要load1000000数据然后基本上全部丢弃,只取10条当然比较慢. 当时我们可以修改为select * from table where id in (select id from table where age &gt; 20 limit 1000000,10).这样虽然也load了一百万的数据,<strong>但是由于索引覆盖,要查询的所有字段都在索引中,所以速度会很快</strong>. 同时如果ID连续的好,我们还可以select * from table where id &gt; 1000000 limit 10,效率也是不错的,优化的可能性有许多种,但是<strong>核心思想都一样,就是减少load的数据</strong>.</p>
</li>
<li><p>从需求的角度减少这种请求….主要是不做类似的需求(直接跳转到几百万页之后的具体某一页.只允许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连续被人恶意攻击.</p>
</li>
</ul>
<blockquote>
<p><strong>解决超大分页,其实主要是靠缓存,可预测性的提前查到内容,缓存至redis等k-V数据库中,直接返回即可</strong>。</p>
</blockquote>
<p>在阿里巴巴《Java开发手册》中,对超大分页的解决办法是类似于上面提到的第一种.</p>
<p><img src="http://5b0988e595225.cdn.sohucs.com/images/20190806/4e8f26a9babf45fdab86ece9c0f96967.jpeg" alt="img"></p>
<p><strong>5. 关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过?</strong></p>
<p>在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时,慢查询的统计主要由运维在做,会定期将业务中的慢查询反馈给我们.</p>
<p>慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?</p>
<p>所以优化也是针对这三个方向来的,</p>
<blockquote>
<ul>
<li>首先分析语句,<strong>看看是否load了额外的数据</strong>,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写.</li>
<li>分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引.</li>
<li>如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表.</li>
</ul>
</blockquote>
<p><strong>6. 上面提到横向分表和纵向分表,可以分别举一个适合他们的例子吗?</strong></p>
<p>横向分表是按行分表.假设我们有一张用户表,主键是自增ID且同时是用户的ID.数据量较大,有1亿多条,那么此时放在一张表里的查询效果就不太理想.我们可以根据主键ID进行分表,无论是按尾号分,或者按ID的区间分都是可以的. 假设按照尾号0-99分为100个表,那么每张表中的数据就仅有100w.这时的查询效率无疑是可以满足要求的.</p>
<p>纵向分表是按列分表.假设我们现在有一张文章表.包含字段id-摘要-内容.而系统中的展示形式是刷新出一个列表,列表中仅包含标题和摘要,当用户点击某篇文章进入详情时才需要正文内容.此时,如果数据量大,将内容这个很大且不经常使用的列放在一起会拖慢原表的查询速度.我们可以将上面的表分为两张.id-摘要,id-内容.当用户点击详情,那主键再来取一次内容即可.而增加的存储量只是很小的主键字段.代价很小.</p>
<p>当然,分表其实和业务的关联度很高,在分表之前一定要做好调研以及benchmark.不要按照自己的猜想盲目操作.</p>
<p><strong>7. 什么是存储过程？有哪些优缺点？</strong></p>
<p>存储过程是一些预编译的SQL语句。1、更加直白的理解：存储过程可以说是一个记录集，它是由一些T-SQL语句组成的代码块，这些T-SQL语句代码像一个方法一样实现一些功能（对单表或多表的增删改查），然后再给这个代码块取一个名字，在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块，执行效率比较高,一个存储过程替代大量T_SQL语句 ，可以降低网络通信量，提高通信速率,可以一定程度上确保数据安全</p>
<p>但是,在互联网项目中,其实是不太推荐存储过程的,比较出名的就是阿里的《Java开发手册》中禁止使用存储过程,我个人的理解是,在互联网项目中,迭代太快,项目的生命周期也比较短,人员流动相比于传统的项目也更加频繁,在这样的情况下,存储过程的管理确实是没有那么方便,同时,复用性也没有写在服务层那么好.</p>
<p><strong>8. 说一说三个范式</strong></p>
<p>第一范式: 每个列都不可以再拆分. 第二范式: 非主键列完全依赖于主键,而不能是依赖于主键的一部分. 第三范式: 非主键列只依赖于主键,不依赖于其他非主键.</p>
<p>在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由.比如性能. 事实上我们经常会为了性能而妥协数据库的设计.</p>
<p><strong>9. MyBatis中的#</strong></p>
<p>乱入了一个奇怪的问题…..我只是想单独记录一下这个问题,因为出现频率太高了.</p>
<p># 会将传入的内容当做字符串,而有什么区别?∗∗乱入了一个奇怪的问题…..我只是想单独记录一下这个问题,因为出现频率太高了.#会将传入的内容当做字符串,而会直接将传入值拼接在sql语句中.</p>
<p>所以#可以在一定程度上预防sql注入攻击.</p>
<h1 id="二、MySQL-常见面试题汇总"><a href="#二、MySQL-常见面试题汇总" class="headerlink" title="二、MySQL 常见面试题汇总"></a>二、MySQL 常见面试题汇总</h1><h2 id="一、存储引擎"><a href="#一、存储引擎" class="headerlink" title="一、存储引擎"></a>一、存储引擎</h2><p>MySQL常见的两种存储引擎：MyISAM与InnoDB</p>
<h2 id="二、字符集及校对规则"><a href="#二、字符集及校对规则" class="headerlink" title="二、字符集及校对规则"></a>二、字符集及校对规则</h2><p>字符集指的是一种从二进制编码到某类字符符号的映射。校对规则则是指某种字符集下的排序规则。Mysql中每一种字符集都会对应一系列的校对规则。</p>
<p>Mysql采用的是类似继承的方式指定字符集的默认值，每个数据库以及每张数据表都有自己的默认值，他们逐层继承。比如：某个库中所有表的默认字符集将是该数据库所指定的字符集（这些表在没有指定字符集的情况下，才会采用默认字符集） </p>
<h2 id="三、索引"><a href="#三、索引" class="headerlink" title="三、索引"></a>三、索引</h2><p>Mysql索引使用的数据结构主要有<strong>BTree索引</strong> 和 <strong>哈希索引</strong> 。对于哈希索引来说，底层的数据结构就是哈希表，因此在绝大多数需求为单条记录查询的时候，可以选择哈希索引，查询性能最快；其余大部分场景，建议选择BTree索引。</p>
<p>Mysql的BTree索引使用的是B数中的B+Tree，但对于主要的两种存储引擎的实现方式是不同的。</p>
<p>  <strong>MyISAM:</strong> B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候，首先按照B+Tree搜索算法搜索索引，如果指定的Key存在，则取出其data域的值，然后以data域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。</p>
<p>  <strong>InnoDB:</strong> 其数据文件本身就是索引文件。相比MyISAM，索引文件和数据文件是分离的，其表数据文件本身就是按B+Tree组织的一个索引结构，树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键，因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引（或聚集索引）”。而其余的索引都作为辅助索引，辅助索引的data域存储相应记录主键的值而不是地址，这也是和MyISAM不同的地方。<strong>在根据主索引搜索时，直接找到key所在的节点即可取出数据；在根据辅助索引查找时，则需要先取出主键的值，在走一遍主索引。</strong> <strong>因此，在设计表的时候，不建议使用过长的字段作为主键，也不建议使用非单调的字段作为主键，这样会造成主索引频繁分裂。</strong></p>
<h2 id="四、缓存"><a href="#四、缓存" class="headerlink" title="四、缓存"></a><strong>四、缓存</strong></h2><p>my.cnf加入以下配置，重启Mysql开启查询缓存</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">query_cache_type=1</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">query_cache_size=600000</span><br></pre></td></tr></table></figure>

<p>Mysql执行以下命令也可以开启查询缓存</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set</span> global  query_cache_type=1;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> global  query_cache_size=600000;</span><br></pre></td></tr></table></figure>

<p>如上，<strong>开启查询缓存后在同样的查询条件以及数据情况下，会直接在缓存中返回结果</strong>。这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。因此任何两个查询在任何字符上的不同都会导致缓存不命中。此外，如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、Mysql库中的系统表，其查询结果也不会被缓存。</p>
<p>缓存建立之后，Mysql的查询缓存系统会跟踪查询中涉及的每张表，如果这些表（数据或结构）发生变化，那么和这张表相关的所有缓存数据都将失效。</p>
<p><strong>缓存虽然能够提升数据库的查询性能，但是缓存同时也带来了额外的开销，每次查询后都要做一次缓存操作，失效后还要销毁。</strong> 因此，开启缓存查询要谨慎，尤其对于写密集的应用来说更是如此。如果开启，要注意合理控制缓存空间大小，一般来说其大小设置为几十MB比较合适。此外，<strong>还可以通过sql_cache和sql_no_cache来控制某个查询语句是否需要缓存：</strong></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select sql_no_cache count(*) from usr;</span><br></pre></td></tr></table></figure>

<h2 id="五、事务"><a href="#五、事务" class="headerlink" title="五、事务"></a>五、事务</h2><p><strong>关系性数据库需要遵循ACID规则，具体内容如下：</strong> </p>
<ol>
<li><strong>原子性：</strong> 事务是最小的执行单位，不允许分割。事务的原子性确保动作要么全部完成，要么完全不起作用；</li>
<li><strong>一致性：</strong> 执行事务前后，数据保持一致；</li>
<li><strong>隔离性：</strong> 并发访问数据库时，一个用户的事物不被其他事物所干扰，各并发事务之间数据库是独立的；</li>
<li><strong>持久性:</strong> 一个事务被提交之后。它对数据库中数据的改变是持久的，即使数据库 发生故障也不应该对其有任何影响。</li>
</ol>
<p><strong>为了达到上述事务特性，数据库定义了几种不同的事务隔离级别：</strong></p>
<ul>
<li><p><strong>READ_UNCOMMITTED（未授权读取）:</strong> 最低的隔离级别，允许读取尚未提交的数据变更，<strong>可能会导致脏读、幻读或不可重复读</strong></p>
</li>
<li><p><strong>READ_COMMITTED（授权读取）:</strong> 允许读取并发事务已经提交的数据，<strong>可以阻止脏读，但是幻读或不可重复读仍有可能发生</strong></p>
</li>
<li><p><strong>REPEATABLE_READ（可重复读）:</strong> 对同一字段的多次读取结果都是一致的，除非数据是被本身事务自己所修改，<strong>可以阻止脏读和不可重复读，但幻读仍有可能发生。</strong></p>
</li>
<li><p><strong>SERIALIZABLE（串行）:</strong> 最高的隔离级别，完全服从ACID的隔离级别。所有的事务依次逐个执行，这样事务之间就完全不可能产生干扰，也就是说，<strong>该级别可以防止脏读、不可重复读以及幻读</strong>。但是这将严重影响程序的性能。通常情况下也不会用到该级别。</p>
<p>这里需要注意的是：<strong>Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.</strong></p>
<p>事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVVC（多版本并发控制），通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。</p>
</li>
</ul>
<h2 id="六、锁"><a href="#六、锁" class="headerlink" title="六、锁"></a>六、锁</h2><p><strong>MyISAM和InnoDB存储引擎使用的锁：</strong></p>
<ul>
<li><p>MyISAM采用表级锁(table-level locking)。</p>
</li>
<li><p>InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁</p>
<p><strong>表级锁和行级锁对比：</strong></p>
</li>
<li><p><strong>表级锁：</strong> Mysql中锁定 <strong>粒度最大</strong> 的一种锁，对当前操作的整张表加锁，实现简单，资源消耗也比较少，加锁快，不会出现死锁。其锁定粒度最大，触发锁冲突的概率最高，并发度最低，MyISAM和 InnoDB引擎都支持表级锁。</p>
</li>
<li><p><strong>行级锁：</strong> Mysql中锁定 <strong>粒度最小</strong> 的一种锁，只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小，并发度高，但加锁的开销也最大，加锁慢，会出现死锁。</p>
<p><strong>InnoDB存储引擎的锁的算法有三种：</strong></p>
</li>
<li><p>Record lock：单个行记录上的锁</p>
</li>
<li><p>Gap lock：间隙锁，锁定一个范围，不包括记录本身</p>
</li>
<li><p>Next-key lock：record+gap 锁定一个范围，包含记录本身</p>
</li>
</ul>
<h2 id="七、大表优化"><a href="#七、大表优化" class="headerlink" title="七、大表优化"></a>七、大表优化</h2><p>当MySQL单表记录数过大时，数据库的CRUD性能会明显下降，一些常见的优化措施如下：</p>
<ol>
<li><p><strong>限定数据的范围：</strong> 务必禁止不带任何限制数据范围条件的查询语句。比如：我们当用户在查询订单历史的时候，我们可以控制在一个月的范围内。；</p>
</li>
<li><p><strong>读/写分离：</strong> 经典的数据库拆分方案，主库负责写，从库负责读；</p>
</li>
<li><p><strong>缓存：</strong> 使用MySQL的缓存，另外对重量级、更新少的数据可以考虑使用应用级别的缓存；</p>
</li>
<li><p><strong>垂直分区：</strong></p>
<p><strong>根据数据库里面数据表的相关性进行拆分。</strong> 例如，用户表中既有用户的登录信息又有用户的基本信息，可以将用户表拆分成两个单独的表，甚至放到单独的库做分库。</p>
<p><strong>简单来说垂直拆分是指数据表列的拆分，把一张列比较多的表拆分为多张表。</strong> 如下图所示，这样来说大家应该就更容易理解了。</p>
</li>
</ol>
<p><img src="https://img-blog.csdn.net/20181014212342809" alt="img"></p>
<p><strong>垂直拆分的优点：</strong> 可以使得行数据变小，在查询时减少读取的Block数，减少I/O次数。此外，垂直分区可以简化表的结构，易于维护。</p>
<p><strong>垂直拆分的缺点：</strong> 主键会出现冗余，需要管理冗余列，并会引起Join操作，可以通过在应用层进行Join来解决。此外，垂直分区会让事务变得更加复杂；</p>
<p>​    <strong>5. 水平分区：</strong></p>
<p><strong>保持数据表结构不变，通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中，达到了分布式的目的。 水平拆分可以支撑非常大的数据量。</strong></p>
<p>水平拆分是指数据表行的拆分，表的行数超过200万行时，就会变慢，这时可以把一张的表的数据拆成多张表来存放。举个例子：我们可以将用户信息表拆分成多个用户信息表，这样就可以避免单一表数据量过大对性能造成影响。</p>
<p><img src="https://img-blog.csdn.net/20181014212446908" alt="img"></p>
<p>水品拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题，但由于表的数据还是在同一台机器上，其实对于提升MySQL 并发能力没有什么意义，所以 <strong>水品拆分最好分库</strong> 。</p>
<p>水平拆分能够 <strong>支持非常大的数据量存储，应用端改造也少</strong>，但 <strong>分片事务难以解决</strong> ，跨界点Join 性能较差，逻辑复杂。《Java工程师修炼之道》的作者推荐 <strong>尽量不要对数据进行分片，因为拆分会带来逻辑、部署、运维的各种复杂度</strong> ，一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片，尽量选择客户端分片架构，这样可以减少一次和中间件的网络 I/O。</p>
<p><strong>下面补充一下数据库分片的两种常见方案：</strong></p>
<ul>
<li><strong>客户端代理：</strong> <strong>分片逻辑在应用端，封装在jar包中，通过修改或者封装JDBC层来实现。</strong> 当当网的 <strong>Sharding-JDBC</strong> 、阿里的TDDL是两种比较常用的实现。</li>
<li><strong>中间件代理：</strong> <strong>在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。</strong> 我们现在谈的 <strong>Mycat</strong>、360的Atlas、网易的DDB等等都是这种架构的实现。</li>
</ul>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/06/08/MySQL%E9%9D%A2%E8%AF%95%E7%AC%94%E8%AE%B0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-设计模式学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/05/27/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%AD%A6%E4%B9%A0/">设计模式学习</a>
    </h1>
  

        
        <a href="/2021/05/27/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-05-27T13:59:38.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-05-27</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="1-软件设计模式的基本要素"><a href="#1-软件设计模式的基本要素" class="headerlink" title="1.软件设计模式的基本要素"></a>1.软件设计模式的基本要素</h1><p>软件设计模式使人们可以更加简单方便地复用成功的设计和体系结构，它通常包含以下几个基本要素：模式名称、别名、动机、问题、解决方案、效果、结构、模式角色、合作关系、实现方法、适用性、已知应用、例程、模式扩展和相关模式等，其中最关键的元素包括以下 4 个主要部分。</p>
<h4 id="1-模式名称"><a href="#1-模式名称" class="headerlink" title="1. 模式名称"></a>1. 模式名称</h4><blockquote>
<p>每一个模式都有自己的名字，通常用一两个词来描述，可以根据模式的问题、特点、解决方案、功能和效果来命名。模式名称（PatternName）有助于我们理解和记忆该模式，也方便我们来讨论自己的设计。</p>
</blockquote>
<h4 id="2-问题"><a href="#2-问题" class="headerlink" title="2. 问题"></a>2. 问题</h4><blockquote>
<p>问题（Problem）描述了该模式的应用环境，即何时使用该模式。它解释了设计问题和问题存在的前因后果，以及必须满足的一系列先决条件。</p>
</blockquote>
<h4 id="3-解决方案"><a href="#3-解决方案" class="headerlink" title="3. 解决方案"></a>3. 解决方案</h4><blockquote>
<p>模式问题的解决方案（Solution）包括设计的组成成分、它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板，可应用于多种不同场合，所以解决方案并不描述一个特定而具体的设计或实现，而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合（类或对象的 组合）来解决这个问题。</p>
</blockquote>
<h4 id="4-效果"><a href="#4-效果" class="headerlink" title="4. 效果"></a>4. 效果</h4><blockquote>
<p>描述了模式的应用效果以及使用该模式应该权衡的问题，即模式的优缺点。主要是对时间和空间的衡量，以及该模式对系统的灵活性、扩充性、可移植性的影响，也考虑其实现问题。显式地列出这些效果（Consequence）对理解和评价这些模式有很大的帮助。</p>
</blockquote>
<h1 id="2-设计模式分类："><a href="#2-设计模式分类：" class="headerlink" title="2.设计模式分类："></a>2.设计模式分类：</h1><p>23种设计模式又称“GoF-23”.根据模式是用来完成什么工作来划分，这种方式可分为<strong>创建型模式、结构型模式和行为型模式</strong> 3 种。</p>
<blockquote>
<ol>
<li><strong>创建型模式</strong>：<strong>用于描述“怎样创建对象”</strong>，它的主要特点是“将对象的创建与使用分离”。GoF 中提供了<strong>单例、原型、工厂方法、抽象工厂、建造者</strong>等 5 种创建型模式。</li>
<li><strong>结构型模式</strong>：用于描述如何将类或对象按某种布局<strong>组成更大的结构</strong>，GoF 中提供了<strong>代理、适配器、桥接、装饰、外观、享元、组合</strong>等 7 种结构型模式。</li>
<li><strong>行为型模式</strong>：用于描述类或对象之间怎样相互协作<strong>共同完成单个对象都无法单独完成的任</strong>务，以及怎样分配职责。GoF 中提供了<strong>模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器</strong>等 11 种行为型模式。</li>
</ol>
</blockquote>
<p><img src="/2021/05/27/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%AD%A6%E4%B9%A0/Java_Projects\Blog\source_posts\设计模式学习\设计模式分类.jpg" alt="设计模式分类"></p>
<blockquote>
<ol>
<li>单例（Singleton）模式：某个类只能生成一个实例，该类提供了一个全局访问点供外部获取该实例，其拓展是有限多例模式。</li>
<li>原型（Prototype）模式：将一个对象作为原型，通过对其进行复制而克隆出多个和原型类似的新实例。</li>
<li>工厂方法（Factory Method）模式：定义一个用于创建产品的接口，由子类决定生产什么产品。</li>
<li>抽象工厂（AbstractFactory）模式：提供一个创建产品族的接口，其每个子类可以生产一系列相关的产品。</li>
<li>建造者（Builder）模式：将一个复杂对象分解成多个相对简单的部分，然后根据不同需要分别创建它们，最后构建成该复杂对象。</li>
<li>代理（Proxy）模式：为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象，从而限制、增强或修改该对象的一些特性。</li>
<li>适配器（Adapter）模式：将一个类的接口转换成客户希望的另外一个接口，使得原本由于接口不兼容而不能一起工作的那些类能一起工作。</li>
<li>桥接（Bridge）模式：将抽象与实现分离，使它们可以独立变化。它是用组合关系代替继承关系来实现，从而降低了抽象和实现这两个可变维度的耦合度。</li>
<li>装饰（Decorator）模式：动态的给对象增加一些职责，即增加其额外的功能。</li>
<li>外观（Facade）模式：为多个复杂的子系统提供一个一致的接口，使这些子系统更加容易被访问。</li>
<li>享元（Flyweight）模式：运用共享技术来有效地支持大量细粒度对象的复用。</li>
<li>组合（Composite）模式：将对象组合成树状层次结构，使用户对单个对象和组合对象具有一致的访问性。</li>
<li>模板方法（TemplateMethod）模式：定义一个操作中的算法骨架，而将算法的一些步骤延迟到子类中，使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。</li>
<li>策略（Strategy）模式：定义了一系列算法，并将每个算法封装起来，使它们可以相互替换，且算法的改变不会影响使用算法的客户。</li>
<li>命令（Command）模式：将一个请求封装为一个对象，使发出请求的责任和执行请求的责任分割开。</li>
<li>职责链（Chain of Responsibility）模式：把请求从链中的一个对象传到下一个对象，直到请求被响应为止。通过这种方式去除对象之间的耦合。</li>
<li>状态（State）模式：允许一个对象在其内部状态发生改变时改变其行为能力。</li>
<li>观察者（Observer）模式：多个对象间存在一对多关系，当一个对象发生改变时，把这种改变通知给其他多个对象，从而影响其他对象的行为。</li>
<li>中介者（Mediator）模式：定义一个中介对象来简化原有对象之间的交互关系，降低系统中对象间的耦合度，使原有对象之间不必相互了解。</li>
<li>迭代器（Iterator）模式：提供一种方法来顺序访问聚合对象中的一系列数据，而不暴露聚合对象的内部表示。</li>
<li>访问者（Visitor）模式：在不改变集合元素的前提下，为一个集合中的每个元素提供多种访问方式，即每个元素有多个访问者对象访问。</li>
<li>备忘录（Memento）模式：在不破坏封装性的前提下，获取并保存一个对象的内部状态，以便以后恢复它。</li>
<li>解释器（Interpreter）模式：提供如何定义语言的文法，以及对语言句子的解释方法，即解释器。</li>
</ol>
</blockquote>
<h1 id="3-OOP七大原则："><a href="#3-OOP七大原则：" class="headerlink" title="3.OOP七大原则："></a>3.OOP七大原则：</h1><blockquote>
<p><strong>开闭原则</strong>：软件实体应当对扩展开放，对修改关闭</p>
<blockquote>
<p>当应用的需求改变时，在不修改软件实体的源代码或者二进制代码的前提下，可以扩展模块的功能，使其满足新的需求。</p>
</blockquote>
<p><strong>里氏替换原则</strong>：继承必须确保超类所拥有的性质在子类中仍然成立.</p>
<blockquote>
<p>子类可以扩展父类的功能，但不能改变父类原有的功能。</p>
</blockquote>
<p><strong>依赖倒置原则</strong>：要面向接口编程，不要面向实现编程。</p>
<blockquote>
<p>降低了客户与实现模块之间的耦合;</p>
<p>细节具有多变性，而抽象层则相对稳定，因此以抽象为基础搭建起来的架构要比以细节为基础搭建起来的架构要稳定得多。这里的抽象指的是接口或者抽象类，而细节是指具体的实现类。</p>
</blockquote>
<p><strong>单一职责原则</strong>：控制类的粒度大小、将对象解耦、提高其内聚性。</p>
<blockquote>
<p>该原则提出对象不应该承担太多职责，如果一个对象承担了太多的职责.</p>
</blockquote>
<p><strong>接口隔离原则</strong>：要为各个类建立它们需要的专用接口，而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。</p>
<blockquote>
<p>尽量将臃肿庞大的接口拆分成更小的和更具体的接口，让接口中只包含客户感兴趣的方法。</p>
</blockquote>
<p><strong>迪米特原则</strong>：最少知识原则,即只与你的直接朋友交谈，不跟“陌生人”说话</p>
<blockquote>
<p>如果两个软件实体无须直接通信，那么就不应当发生直接的相互调用，可以通过第三方转发该调用。其目的是降低类之间的耦合度，提高模块的相对独立性。</p>
</blockquote>
<p><strong>合成复用原则</strong>：在软件复用时，要尽量先使用组合或者聚合等关联关系来实现，其次才考虑使用继承关系来实现。</p>
<blockquote>
<p>如果要使用继承关系，则必须严格遵循里氏替换原则。</p>
</blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>设计原则</th>
<th>一句话归纳</th>
<th>目的</th>
</tr>
</thead>
<tbody><tr>
<td>开闭原则</td>
<td>对扩展开放，对修改关闭</td>
<td>降低维护带来的新风险</td>
</tr>
<tr>
<td>依赖倒置原则</td>
<td>高层不应该依赖低层，要面向接口编程</td>
<td>更利于代码结构的升级扩展</td>
</tr>
<tr>
<td>单一职责原则</td>
<td>一个类只干一件事，实现类要单一</td>
<td>便于理解，提高代码的可读性</td>
</tr>
<tr>
<td>接口隔离原则</td>
<td>一个接口只干一件事，接口要精简单一</td>
<td>功能解耦，高聚合、低耦合</td>
</tr>
<tr>
<td>迪米特法则</td>
<td>不该知道的不要知道，一个类应该保持对其它对象最少的了解，降低耦合度</td>
<td>只和朋友交流，不和陌生人说话，减少代码臃肿</td>
</tr>
<tr>
<td>里氏替换原则</td>
<td>不要破坏继承体系，子类重写方法功能发生改变，不应该影响父类方法的含义</td>
<td>防止继承泛滥</td>
</tr>
<tr>
<td>合成复用原则</td>
<td>尽量使用组合或者聚合关系实现代码复用，少使用继承</td>
<td>降低代码耦合</td>
</tr>
</tbody></table>
<p>实际上，这些原则的目的只有一个：降低对象之间的耦合，增加程序的可复用性、可扩展性和可维护性。</p>
<blockquote>
<p>记忆口诀：访问加限制，函数要节俭，依赖不允许，动态加接口，父类要抽象，扩展不更改。</p>
</blockquote>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/05/27/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Shiro" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="Shiro"><a href="#Shiro" class="headerlink" title="Shiro"></a>Shiro</h1><p>什么是 Shiro</p>
<p>官网：<a target="_blank" rel="noopener" href="http://shiro.apache.org/">http://shiro.apache.org/</a></p>
<p>是一款主流的 Java 安全框架，不依赖任何容器，可以运行在 Java SE 和 Java EE 项目中，它的主要作用是对访问系统的用户进行身份认证、授权、会话管理、加密等操作。</p>
<p>Shiro 就是用来解决安全管理的系统化框架。</p>
<p>使用流程：</p>
<blockquote>
<p>(1)<strong>在Realm中完成认证（Authentication）和授权（Authorize）的逻辑</strong>；</p>
<p>(2)在Config中完成从AccountRealm→DefaultWebSecurityManager→ShiroFilterFactoryBean的配置；</p>
</blockquote>
<h1 id="Shiro-核心组件"><a href="#Shiro-核心组件" class="headerlink" title="Shiro 核心组件"></a>Shiro 核心组件</h1><p>用户、角色、权限三者相互关联。即<strong>某个人（用户）具备某种角色身份，具有相应的权限。</strong></p>
<p><strong>会给角色赋予权限，给用户赋予角色</strong></p>
<p>1、UsernamePasswordToken，Shiro 用来封装用户登录信息，使用用户的登录信息来创建令牌 Token。</p>
<p>2、<strong>SecurityManager，Shiro 的核心部分</strong>，负责安全认证和授权。</p>
<p>3、Subject，Shiro 的一个抽象概念，包含了用户信息。</p>
<p>4、Realm，开发者自定义的模块，根据项目的需求，<strong>验证和授权的逻辑全部写在 Realm 中</strong>。</p>
<p>5、AuthenticationInfo，用户的角色信息集合，认证时使用。</p>
<p>6、AuthorizationInfo，角色的权限信息集合，授权时使用。</p>
<p>7、DefaultWebSecurityManager，安全管理器，<strong>开发者自定义的 Realm 需要注入到 DefaultWebSecurityManager 进行管理才</strong>能生效。</p>
<p>8、ShiroFilterFactoryBean，过滤器工厂，<strong>Shiro 的基本运行机制是开发者定制规则，Shiro 去执行</strong>，具体的执行操作就是由 ShiroFilterFactoryBean 创建的一个个 Filter 对象来完成。</p>
<p>Shiro 的运行机制如下图所示。</p>
<p><img src="/2021/05/26/Shiro/Users\FangBiao\AppData\Roaming\Typora\typora-user-images\image-20210525172744054.png" alt="image-20210525172744054"></p>
<h1 id="Spring-Boot-整合-Shiro"><a href="#Spring-Boot-整合-Shiro" class="headerlink" title="Spring Boot 整合 Shiro"></a>Spring Boot 整合 Shiro</h1><p>1、创建 Spring Boot 应用，集成 Shiro 及相关组件，<strong>pom.xml</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-thymeleaf<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.projectlombok<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>lombok<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">optional</span>&gt;</span>true<span class="tag">&lt;/<span class="name">optional</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.shiro<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>shiro-spring<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.5.3<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.baomidou<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis-plus-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.3.1.tmp<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.junit.vintage<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>junit-vintage-engine<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>2、<strong>自定义 Shiro 过滤器</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AccoutRealm</span> <span class="keyword">extends</span> <span class="title">AuthorizingRealm</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AccountService accountService;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 授权</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> principalCollection</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> AuthorizationInfo <span class="title">doGetAuthorizationInfo</span><span class="params">(PrincipalCollection principalCollection)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 认证：即将用户输入的信息封装成token,然后根据token中的用户名进行数据库查找；如果存在，再验证密码；</span></span><br><span class="line"><span class="comment">     当二者均正确时，验证完成。</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> authenticationToken</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> AuthenticationException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> AuthenticationInfo <span class="title">doGetAuthenticationInfo</span><span class="params">(AuthenticationToken authenticationToken)</span> <span class="keyword">throws</span> AuthenticationException </span>&#123;</span><br><span class="line">        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;</span><br><span class="line">        Account account = accountService.findByUsername(token.getUsername());</span><br><span class="line">        <span class="keyword">if</span>(account != <span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> SimpleAuthenticationInfo(account,account.getPassword(),getName());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、<strong>配置类</strong>:accoutRealm→securityManager→shiroFilterFactoryBean</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ShiroConfig</span> </span>&#123;</span><br><span class="line">    <span class="comment">/*将之前写好的AccountRealm类注入;安全组件、工厂等一起注入;</span></span><br><span class="line"><span class="comment">    * 顺序为;先创建一个AccountRealm实体类；然后将其注入到manager中；再将manager注入到工厂中*/</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ShiroFilterFactoryBean <span class="title">shiroFilterFactoryBean</span><span class="params">(<span class="meta">@Qualifier(&quot;securityManager&quot;)</span> DefaultWebSecurityManager securityManager)</span></span>&#123;</span><br><span class="line">        ShiroFilterFactoryBean factoryBean = <span class="keyword">new</span> ShiroFilterFactoryBean();</span><br><span class="line">        factoryBean.setSecurityManager(securityManager);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">//1.设置权限管理内容</span></span><br><span class="line">        Map&lt;String,String&gt; map = <span class="keyword">new</span> Hashtable&lt;&gt;();</span><br><span class="line">        map.put(<span class="string">&quot;/main&quot;</span>,<span class="string">&quot;authc&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;/manage&quot;</span>,<span class="string">&quot;perms[manage]&quot;</span>);</span><br><span class="line">        map.put(<span class="string">&quot;/administrator&quot;</span>,<span class="string">&quot;roles[administrator]&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.将权限注入到工厂中</span></span><br><span class="line">        factoryBean.setFilterChainDefinitionMap(map);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//3.设置登录页面，实现按照自己的设置进行跳转</span></span><br><span class="line">        factoryBean.setLoginUrl(<span class="string">&quot;/login&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//4.shiro框架中的设置未授权页面</span></span><br><span class="line">        factoryBean.setUnauthorizedUrl(<span class="string">&quot;/unauth&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> factoryBean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> DefaultWebSecurityManager <span class="title">securityManager</span><span class="params">(<span class="meta">@Qualifier(&quot;accoutRealm&quot;)</span> AccoutRealm accoutRealm)</span></span>&#123;</span><br><span class="line">        DefaultWebSecurityManager manager = <span class="keyword">new</span> DefaultWebSecurityManager();</span><br><span class="line">        manager.setRealm(accoutRealm);</span><br><span class="line">        <span class="keyword">return</span> manager;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> AccoutRealm <span class="title">accoutRealm</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> AccoutRealm();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/*实现shiro和其他框加的整合*/</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ShiroDialect <span class="title">shiroDialect</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> ShiroDialect();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>编写认证和授权规则：</p>
<blockquote>
<blockquote>
<p>认证过滤器：</p>
<p><strong>anon：无需认证。</strong></p>
<p><strong>authc：必须认证。</strong></p>
<p><strong>authcBasic：需要通过 HTTPBasic 认证。</strong></p>
<p><strong>user：不一定通过认证，只要曾经被 Shiro 记录即可，比如：记住我。</strong></p>
</blockquote>
<blockquote>
<p>授权过滤器：</p>
<p><strong>perms：必须拥有某个权限才能访问。</strong></p>
<p><strong>role：必须拥有某个角色才能访问。</strong></p>
<p><strong>port：请求的端口必须是指定值才可以。</strong></p>
<p><strong>rest：请求必须基于 RESTful，POST、PUT、GET、DELETE。</strong></p>
<p><strong>ssl：必须是安全的 URL 请求，协议 HTTPS。</strong></p>
</blockquote>
</blockquote>
<p>创建 3 个页面，main.html、manage.html、administrator.html，要求达到的目的：</p>
<blockquote>
<p>访问权限如下：</p>
<p>1、必须登录才能访问 main.html</p>
<p>2、当前用户必须拥有 manage 授权才能访问 manage.html</p>
<p>3、当前用户必须拥有 administrator 角色才能访问 administrator.html</p>
</blockquote>
<p><strong>4、登录信息等显示与销毁问题：</strong></p>
<blockquote>
<ul>
<li>在页面中显示“xxx欢迎回来”的效果：</li>
</ul>
<blockquote>
<p>先从shiro中获取到subject对象（保存的内容，如Account），将其存入到session中；然后到页面显示即可。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&#x2F;&#x2F;在controller中完成“当成功登录时，使用session存储信息”</span><br><span class="line"></span><br><span class="line">		subject.login(token);</span><br><span class="line">           &#x2F;&#x2F;用户登录成功后，将其相关信息进行存入到Session中，方便使用</span><br><span class="line">           Account account &#x3D; (Account) subject.getPrincipal();</span><br><span class="line">           subject.getSession().setAttribute(&quot;account&quot;,account);</span><br><span class="line"></span><br><span class="line">           return &quot;index&quot;;</span><br></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&lt;body&gt;</span><br><span class="line">       &lt;h2&gt;Index&lt;/h2&gt;</span><br><span class="line">       &lt;div th:<span class="keyword">if</span>=<span class="string">&quot;$&#123;session.account !=null&#125;&quot;</span>&gt;</span><br><span class="line">           &lt;span th:text=&quot;$&#123;session.account.username&#125;+&#x27;欢迎回来！&#x27;&quot;&gt;&lt;/span&gt; </span><br><span class="line"></span><br><span class="line">       &lt;/div&gt;</span><br><span class="line">       &lt;a href=&quot;/main&quot;&gt;main&lt;/a&gt; &lt;br/&gt;</span><br><span class="line">&gt;&gt;&lt;/body&gt;</span><br></pre></td></tr></table></figure>
</blockquote>
<ul>
<li><p>点击“退出登录”的效果：</p>
<blockquote>
<p>对于退出操作，只需在Controller中获取到session进行销毁即可。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&gt;@GetMapping(&quot;&#x2F;logout&quot;)</span><br><span class="line">  public String logout()&#123;</span><br><span class="line">      &#x2F;&#x2F;拿到shiro中存储的信息，执行对应销毁方法即可</span><br><span class="line">      Subject subject &#x3D; SecurityUtils.getSubject();</span><br><span class="line">      subject.logout();</span><br><span class="line">      return &quot;login&quot;;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
</blockquote>
</li>
</ul>
</blockquote>
<h1 id="Shiro-整合-Thymeleaf"><a href="#Shiro-整合-Thymeleaf" class="headerlink" title="Shiro 整合 Thymeleaf"></a>Shiro 整合 Thymeleaf</h1><blockquote>
<p><strong>Shiro 整合 Thymeleaf实现根据权限，只显示对应内容</strong></p>
</blockquote>
<p>1、pom.xml 引入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.github.theborakompanioni<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>thymeleaf-extras-shiro<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.0.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>2、配置类添加 ShiroDialect</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> ShiroDialect <span class="title">shiroDialect</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> ShiroDialect();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、index.html中进行设置</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span> <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span> <span class="attr">xmlns:shiro</span>=<span class="string">&quot;http://www.thymeleaf.org/thymeleaf-extras-shiro&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;shortcut icon&quot;</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span>index<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">th:if</span>=<span class="string">&quot;$&#123;session.account != null&#125;&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">span</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;session.account.username&#125;+&#x27;欢迎回来！&#x27;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;/logout&quot;</span>&gt;</span>退出<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    </span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;/main&quot;</span>&gt;</span>main<span class="tag">&lt;/<span class="name">a</span>&gt;</span> <span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">    </span><br><span class="line">    //此处为根据权限permission或角色role进行针对性显示</span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">shiro:hasPermission</span>=<span class="string">&quot;manage&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;manage&quot;</span>&gt;</span>manage<span class="tag">&lt;/<span class="name">a</span>&gt;</span> <span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">shiro:hasRole</span>=<span class="string">&quot;administrator&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;/administrator&quot;</span>&gt;</span>administrator<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>
      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/05/26/Shiro/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Json-MySQL学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/05/18/Json-MySQL%E5%AD%A6%E4%B9%A0/">Json &amp; MySQL学习</a>
    </h1>
  

        
        <a href="/2021/05/18/Json-MySQL%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-05-18T10:59:20.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-05-18</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="一、Json学习："><a href="#一、Json学习：" class="headerlink" title="一、Json学习："></a>一、Json学习：</h1><blockquote>
<p>什么是JSON？</p>
</blockquote>
<ul>
<li>JSON(JavaScript Object Notation, JS 对象标记) 是一种<strong>轻量级的数据交换格式</strong>，目前使用特别广泛。</li>
<li>采用<strong>完全独立于编程语言的**</strong>文本格式**来存储和表示数据。</li>
<li>简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。</li>
<li>易于人阅读和编写，同时也易于机器解析和生成，并有效地提升网络传输效率。</li>
</ul>
<p>在 JavaScript 语言中，一切都是对象。因此，任何JavaScript 支持的类型都可以通过 JSON 来表示，例如字符串、数字、对象、数组等。</p>
<h2 id="1-JSON的要求和语法格式："><a href="#1-JSON的要求和语法格式：" class="headerlink" title="1. JSON的要求和语法格式："></a>1. JSON的要求和语法格式：</h2><ul>
<li><strong>对象表示为键值对，数据由逗号分隔</strong></li>
<li><strong>花括号保存对象</strong></li>
<li><strong>方括号保存数组</strong></li>
</ul>
<p><strong>JSON 键值对</strong>是用来保存 JavaScript 对象的一种方式，和 JavaScript 对象的写法也大同小异，<strong>键/值对组合中的键名写在前面并用双引号 “” 包裹，使用冒号 : 分隔，然后紧接着值</strong>：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;&quot;name&quot;: &quot;QinJiang&quot;&#125;</span><br><span class="line">&#123;&quot;age&quot;: &quot;3&quot;&#125;</span><br><span class="line">&#123;&quot;sex&quot;: &quot;男&quot;&#125;</span><br></pre></td></tr></table></figure>



<h2 id="2-JSON-和-JavaScript-对象的关系可以这么理解为："><a href="#2-JSON-和-JavaScript-对象的关系可以这么理解为：" class="headerlink" title="2.JSON 和 JavaScript 对象的关系可以这么理解为："></a>2.JSON 和 JavaScript 对象的关系可以这么理解为：</h2><p><strong>JSON 是 JavaScript 对象的字符串表示法，它使用文本表示一个 JS 对象的信息，本质是一个字符串。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;a: <span class="string">&#x27;Hello&#x27;</span>, b: <span class="string">&#x27;World&#x27;</span>&#125;; <span class="comment">//这是一个对象，注意键名也是可以使用引号包裹的</span></span><br><span class="line"><span class="keyword">var</span> json = <span class="string">&#x27;&#123;&quot;a&quot;: &quot;Hello&quot;, &quot;b&quot;: &quot;World&quot;&#125;&#x27;</span>; <span class="comment">//这是一个 JSON 字符串，本质是一个字符串</span></span><br></pre></td></tr></table></figure>



<h2 id="3-JSON-和-JavaScript-对象互转"><a href="#3-JSON-和-JavaScript-对象互转" class="headerlink" title="3.JSON 和 JavaScript 对象互转:"></a>3.<strong>JSON 和 JavaScript 对象互转</strong>:</h2><p>要实现<strong>从JSON字符串转换为JavaScript 对象，使用 JSON.parse() 方法</strong>：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var obj &#x3D; JSON.parse(&#39;&#123;&quot;a&quot;: &quot;Hello&quot;, &quot;b&quot;: &quot;World&quot;&#125;&#39;);</span><br><span class="line">&#x2F;&#x2F;结果是 &#123;a: &#39;Hello&#39;, b: &#39;World&#39;&#125;</span><br></pre></td></tr></table></figure>

<p>要实现<strong>从JavaScript 对象转换为JSON字符串，使用 JSON.stringify() 方法</strong>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> json = JSON.stringify(&#123;a: <span class="string">&#x27;Hello&#x27;</span>, b: <span class="string">&#x27;World&#x27;</span>&#125;);</span><br><span class="line"><span class="comment">//结果是 &#x27;&#123;&quot;a&quot;: &quot;Hello&quot;, &quot;b&quot;: &quot;World&quot;&#125;&#x27;</span></span><br></pre></td></tr></table></figure>



<h2 id="4-过程中的问题解决："><a href="#4-过程中的问题解决：" class="headerlink" title="4.过程中的问题解决："></a>4.过程中的问题解决：</h2><h3 id="1-乱码统一解决："><a href="#1-乱码统一解决：" class="headerlink" title="(1)乱码统一解决："></a>(1)<strong>乱码统一解决</strong>：</h3><blockquote>
<p>如果项目中有许多请求时，可以通过Spring配置统一指定，这样就不用每次都去处理了！</p>
<p>我们可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter转换配置！</p>
</blockquote>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;mvc:annotation-driven&gt;</span><br><span class="line">   &lt;mvc:message-converters register-defaults=<span class="string">&quot;true&quot;</span>&gt;</span><br><span class="line">       &lt;bean <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;org.springframework.http.converter.StringHttpMessageConverter&quot;</span>&gt;</span><br><span class="line">           &lt;constructor-arg value=<span class="string">&quot;UTF-8&quot;</span>/&gt;</span><br><span class="line">       &lt;/bean&gt;</span><br><span class="line">       &lt;bean <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;org.springframework.http.converter.json.MappingJackson2HttpMessageConverter&quot;</span>&gt;</span><br><span class="line">           &lt;property name=<span class="string">&quot;objectMapper&quot;</span>&gt;</span><br><span class="line">               &lt;bean <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean&quot;</span>&gt;</span><br><span class="line">                   &lt;property name=<span class="string">&quot;failOnEmptyBeans&quot;</span> value=<span class="string">&quot;false&quot;</span>/&gt;</span><br><span class="line">               &lt;/bean&gt;</span><br><span class="line">           &lt;/property&gt;</span><br><span class="line">       &lt;/bean&gt;</span><br><span class="line">   &lt;/mvc:message-converters&gt;</span><br><span class="line">&lt;/mvc:annotation-driven&gt;</span><br></pre></td></tr></table></figure>

<h3 id="2-返回json字符串统一解决"><a href="#2-返回json字符串统一解决" class="headerlink" title="(2)返回json字符串统一解决:"></a>(2)<strong>返回json字符串统一解决</strong>:</h3><blockquote>
<p>在类上直接使用 <strong>@RestController</strong> ，这样子，里面所有的方法都只会返回 json 字符串了，不用再每一个都添加@ResponseBody ！我们在前后端分离开发中，一般都使用 @RestController ，十分便捷！</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">@RestController	&#x2F;&#x2F;在Controller类上使用该注解，可以避免在每一个请求上写@ResponseBody </span><br><span class="line">public class UserController &#123;</span><br><span class="line">   &#x2F;&#x2F;produces:指定响应体返回类型和编码</span><br><span class="line">   @RequestMapping(value &#x3D; &quot;&#x2F;json1&quot;)</span><br><span class="line">   public String json1() throws JsonProcessingException &#123;</span><br><span class="line">       &#x2F;&#x2F;创建一个jackson的对象映射器，用来解析数据</span><br><span class="line">       ObjectMapper mapper &#x3D; new ObjectMapper();</span><br><span class="line">       &#x2F;&#x2F;创建一个对象</span><br><span class="line">       User user &#x3D; new User(&quot;秦疆1号&quot;, 3, &quot;男&quot;);</span><br><span class="line">       &#x2F;&#x2F;将我们的对象解析成为json格式</span><br><span class="line">       String str &#x3D; mapper.writeValueAsString(user);</span><br><span class="line">       &#x2F;&#x2F;由于@ResponseBody注解，这里会将str转成json格式返回；十分方便</span><br><span class="line">       return str;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="3-关于时间戳的问题："><a href="#3-关于时间戳的问题：" class="headerlink" title="(3)关于时间戳的问题："></a>(3)关于时间戳的问题：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@RequestMapping(&quot;&#x2F;json3&quot;)</span><br><span class="line">public String json3() throws JsonProcessingException &#123;</span><br><span class="line"></span><br><span class="line">   ObjectMapper mapper &#x3D; new ObjectMapper();</span><br><span class="line"></span><br><span class="line">   &#x2F;&#x2F;创建时间一个对象，java.util.Date</span><br><span class="line">   Date date &#x3D; new Date();</span><br><span class="line">   &#x2F;&#x2F;将我们的对象解析成为json格式</span><br><span class="line">   String str &#x3D; mapper.writeValueAsString(date);</span><br><span class="line">   return str;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>注意执行结果是一个时间戳值（以ms计算的时间值）</p>
</blockquote>
<blockquote>
<p><strong>改进方案：取消timestamps形式 ， 自定义时间格式</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/json4&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">json4</span><span class="params">()</span> <span class="keyword">throws</span> JsonProcessingException </span>&#123;</span><br><span class="line"></span><br><span class="line">   ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"></span><br><span class="line">   <span class="comment">//不使用时间戳的方式:通过配置关闭时间戳功能</span></span><br><span class="line">   mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, <span class="keyword">false</span>);</span><br><span class="line">   <span class="comment">//自定义日期格式对象</span></span><br><span class="line">   SimpleDateFormat sdf = <span class="keyword">new</span> SimpleDateFormat(<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>);</span><br><span class="line">   <span class="comment">//指定日期格式：即在mapper上绑定该种日期格式化功能</span></span><br><span class="line">   mapper.setDateFormat(sdf);</span><br><span class="line"></span><br><span class="line">   Date date = <span class="keyword">new</span> Date();</span><br><span class="line">   String str = mapper.writeValueAsString(date);</span><br><span class="line"></span><br><span class="line">   <span class="keyword">return</span> str;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(4)工具类封装问题：</p>
<blockquote>
<p><strong>对于要经常使用的代码的话，经常调用的方式是比较麻烦的，我们可以将这些代码封装到一个工具类中</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.core.JsonProcessingException;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.SerializationFeature;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.text.SimpleDateFormat;</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义一个获取json数据的工具类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JsonUtils</span> </span>&#123;</span><br><span class="line">   <span class="comment">//1.此处为方法重载：如果未指定日期格式化方式，则使用默认方式</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getJson</span><span class="params">(Object object)</span> </span>&#123;</span><br><span class="line">       <span class="keyword">return</span> getJson(object,<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">	<span class="comment">//2.根据指定的格式化方法、将对应的对象object转为json数据</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getJson</span><span class="params">(Object object,String dateFormat)</span> </span>&#123;</span><br><span class="line">       ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line">       <span class="comment">//2.1关闭时间差</span></span><br><span class="line">       mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, <span class="keyword">false</span>);</span><br><span class="line">       <span class="comment">//2.2自定义日期格式对象</span></span><br><span class="line">       SimpleDateFormat sdf = <span class="keyword">new</span> SimpleDateFormat(dateFormat);</span><br><span class="line">       <span class="comment">//2.3指定日期格式</span></span><br><span class="line">       mapper.setDateFormat(sdf);</span><br><span class="line">       <span class="keyword">try</span> &#123;</span><br><span class="line">           <span class="keyword">return</span> mapper.writeValueAsString(object);</span><br><span class="line">      &#125; <span class="keyword">catch</span> (JsonProcessingException e) &#123;</span><br><span class="line">           e.printStackTrace();</span><br><span class="line">      &#125;</span><br><span class="line">       <span class="keyword">return</span> <span class="keyword">null</span>;	<span class="comment">//4.防止异常</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>工具类的使用：直接在我们需要处理的请求中，使用该工具类，并调用其中的方法即可。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(&quot;/json5&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">json5</span><span class="params">()</span> <span class="keyword">throws</span> JsonProcessingException </span>&#123;</span><br><span class="line">   Date date = <span class="keyword">new</span> Date();</span><br><span class="line">   String json = JsonUtils.getJson(date);</span><br><span class="line">   <span class="keyword">return</span> json;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="二、MySQL学习："><a href="#二、MySQL学习：" class="headerlink" title="二、MySQL学习："></a>二、MySQL学习：</h1><h3 id="（1）如何处理删除数据后的，数据库不能连续自增问题："><a href="#（1）如何处理删除数据后的，数据库不能连续自增问题：" class="headerlink" title="（1）如何处理删除数据后的，数据库不能连续自增问题："></a>（1）如何处理删除数据后的，数据库不能连续自增问题：</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//1，删除原有主键：</span></span><br><span class="line"></span><br><span class="line">ALTER TABLE `table_name` DROP `id`;</span><br><span class="line"></span><br><span class="line"><span class="comment">//2，添加新主键字段：</span></span><br><span class="line"></span><br><span class="line">ALTER TABLE `table_name` ADD `id` <span class="keyword">int</span> NOT NULL FIRST;</span><br><span class="line"></span><br><span class="line"><span class="comment">//3，设置新主键：</span></span><br><span class="line"></span><br><span class="line">ALTER TABLE `table_name` MODIFY COLUMN `id` <span class="keyword">int</span> NOT NULL AUTO_INCREMENT,<span class="function">ADD PRIMARY <span class="title">KEY</span><span class="params">(id)</span></span>;</span><br></pre></td></tr></table></figure>

<h3 id="（2）让从数据库中查询的数据按某种顺序以倒序输出："><a href="#（2）让从数据库中查询的数据按某种顺序以倒序输出：" class="headerlink" title="（2）让从数据库中查询的数据按某种顺序以倒序输出："></a>（2）让从数据库中查询的数据按某种顺序以倒序输出：</h3><blockquote>
<p><strong>asc是表示升序，desc表示降序。</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select * from `table_name` order by <span class="string">&#x27;id&#x27;</span> desc;</span><br></pre></td></tr></table></figure>


      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/05/18/Json-MySQL%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Nginx&amp;XShell学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/05/10/Nginx&XShell%E5%AD%A6%E4%B9%A0/">Nginx学习</a>
    </h1>
  

        
        <a href="/2021/05/10/Nginx&XShell%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-05-10T07:48:23.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-05-10</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>一、XShell的使用：</p>
<blockquote>
<ol>
<li>姓名：YuSanshui   邮箱：<a href="mailto:&#x32;&#49;&#x38;&#51;&#x34;&#x35;&#x36;&#53;&#53;&#54;&#x40;&#x71;&#113;&#x2e;&#x63;&#x6f;&#109;">&#x32;&#49;&#x38;&#51;&#x34;&#x35;&#x36;&#53;&#53;&#54;&#x40;&#x71;&#113;&#x2e;&#x63;&#x6f;&#109;</a>;</li>
<li></li>
</ol>
</blockquote>
<h1 id="一、正反向代理比较："><a href="#一、正反向代理比较：" class="headerlink" title="一、正反向代理比较："></a>一、正反向代理比较：</h1><h2 id="1、正反向代理概念："><a href="#1、正反向代理概念：" class="headerlink" title="1、正反向代理概念："></a>1、正反向代理概念：</h2><blockquote>
<p>正向代理和反向代理，是从是否客户端角度出发的。</p>
<p><strong>正向代理</strong>：帮助客户端处理请求。即将客户端的请求信息经过中间服务器（代理服务器），由中间者执行请求，向后端的WEB服务器请求相应内容。把获取的内容再转交给客户端。</p>
<p><strong>反向代理</strong>：帮助后端服务器处理请求内容。中间服务器将后端WEB服务器的内容缓存到本地。当客户端请求相应内容时，直接将相应内容转给客户端。</p>
</blockquote>
<h2 id="2、正反向代理的优缺点："><a href="#2、正反向代理的优缺点：" class="headerlink" title="2、正反向代理的优缺点："></a>2、正反向代理的优缺点：</h2><blockquote>
<p>正向代理，<strong>其实是”代理服务器”代理了”客户端”，去和”目标服务器”进行交互。</strong>可以做到突破访问限制（如通过VPN访问外网功能）、提高访问速度(代理服务器将请求信息缓存到本地，下次可直接取出使用)、隐藏客户端真实IP。</p>
<p>反向代理，<strong>其实是”代理服务器”代理了”目标服务器”，去和”客户端”进行交互。</strong>可以做到隐藏服务器的真实IP、负载均衡(根据所有真实服务器的负载情况，将客户端请求分发到不同的真实服务器上)、提高访问速度、提供安全保障(为WEB服务器设置应用层防火墙，免受Dos攻击等行为。)</p>
</blockquote>
<h2 id="3、正反向代理的区别："><a href="#3、正反向代理的区别：" class="headerlink" title="3、正反向代理的区别："></a>3、正反向代理的区别：</h2><blockquote>
<p>虽然正向代理服务器和反向代理服务器所处的<strong>位置都是客户端和真实服务器之间</strong>，<strong>所做的事情也都是把客户端的请求转发给服务器，再把服务器的响应转发给客户端</strong>，但是二者之间还是有一定的差异的。</p>
<p>1、正向代理其实是客户端的代理，帮助客户端访问其无法访问的服务器资源。反向代理则是服务器的代理，帮助服务器做负载均衡，安全防护等。</p>
<p>2、<strong>正向代理一般是客户端架设的，比如在自己的机器上安装一个代理软件。而反向代理一般是服务器架设的，比如在自己的机器集群中部署一个反向代理服务器。</strong></p>
<p>3、正向代理中，服务器不知道真正的客户端到底是谁，以为访问自己的就是真实的客户端。而在反向代理中，客户端不知道真正的服务器是谁，以为自己访问的就是真实的服务器。</p>
<p>4、正向代理和反向代理的作用和目的不同。<strong>正向代理主要是用来解决访问限制问题。而反向代理则是提供负载均衡、安全防护等作用</strong>。二者均能提高访问速度。</p>
</blockquote>
<h1 id="二、Nginx的概念及作用："><a href="#二、Nginx的概念及作用：" class="headerlink" title="二、Nginx的概念及作用："></a>二、Nginx的概念及作用：</h1><h2 id="1、什么是Nginx？"><a href="#1、什么是Nginx？" class="headerlink" title="1、什么是Nginx？"></a>1、什么是Nginx？</h2><blockquote>
<p>Nginx (engine x) 是一个<strong>高性能的HTTP和反向代理web服务器</strong>，同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为<strong>俄罗斯</strong>访问量第二的Rambler.ru站点（俄文：Рамблер）开发的。</p>
<p><strong>其特点是占有内存少，并发能力强</strong>。事实上nginx的并发能力在同类型的网页服务器中表现较好，中国大陆使用nginx网站用户有：百度、京东、新浪、网易、腾讯、淘宝等。在全球活跃的网站中有12.18%的使用比率，大约为2220万个网站。</p>
<p>Nginx 是一个安装非常的简单、配置文件非常简洁（还能够支持perl语法）、Bug非常少的服务。Nginx 启动特别容易，并且几乎可以做到7*24不间断运行，即使运行数个月也不需要重新启动。你还能够不间断服务的情况下进行软件版本的升级。</p>
<p>官方数据测试表明能够支持高达 50,000 个并发连接数的响应。</p>
</blockquote>
<h2 id="2、Nginx的作用："><a href="#2、Nginx的作用：" class="headerlink" title="2、Nginx的作用："></a>2、Nginx的作用：</h2><blockquote>
<p>负载均衡、反向代理、动静分离(即将访问页面的静态资源分离开来，加快下次访问速度。)</p>
</blockquote>
<h2 id="3、使用："><a href="#3、使用：" class="headerlink" title="3、使用："></a>3、使用：</h2><h4 id="1-基础使用："><a href="#1-基础使用：" class="headerlink" title="1.基础使用："></a>1.基础使用：</h4><blockquote>
<p>(1) 下载：<a target="_blank" rel="noopener" href="https://links.jianshu.com/go?to=http://nginx.org/en/download.html">http://nginx.org/en/download.html</a> 下载稳定版本即可。<br>(2) 启动：打开cmd命令窗口，切换到nginx解压目录下，输入命令 <code>nginx.exe</code> ，回车即可。</p>
<p>(3)检查nginx是否启动成功:   直接在浏览器地址栏输入网址 <a target="_blank" rel="noopener" href="https://links.jianshu.com/go?to=http://localhost:80">http://localhost:80</a> 回车，出现“welcome”页面说明启动成功！（注意：此处的80端口为nginx文件conf配置文件中的端口设置，可自行更改。）</p>
</blockquote>
<h4 id="2-配置监听·：配置文件：config文件夹下的nginx-conf文件。"><a href="#2-配置监听·：配置文件：config文件夹下的nginx-conf文件。" class="headerlink" title="2.配置监听·：配置文件：config文件夹下的nginx.conf文件。"></a>2.配置监听·：配置文件：config文件夹下的nginx.conf文件。</h4><blockquote>
<ul>
<li>nginx的配置文件是conf目录下的nginx.conf，默认配置的nginx监听的端口为80，如果80端口被占用可以修改为未被占用的端口即可，在server中配置即可。</li>
<li>当我们修改了nginx的配置文件nginx.conf 时，不需要关闭nginx后重新启动nginx，只需要执行命令 <code>nginx -s reload</code> 即可让改动生效。</li>
</ul>
</blockquote>
<blockquote>
<p>配置负载均衡upstream、访问根路径的代理地址：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&gt;upstream lb&#123;</span><br><span class="line">   server <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">8080</span> weight=<span class="number">1</span>;</span><br><span class="line">   server <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span>:<span class="number">8081</span> weight=<span class="number">1</span>;</span><br><span class="line">&gt;&#125;</span><br><span class="line"></span><br><span class="line">&gt;location / &#123;</span><br><span class="line">   proxy_pass http:<span class="comment">//lb;</span></span><br><span class="line">&gt;&#125;</span><br></pre></td></tr></table></figure>
</blockquote>
<h2 id="4、常用功能："><a href="#4、常用功能：" class="headerlink" title="4、常用功能："></a>4、常用功能：</h2><blockquote>
<h3 id="Nginx的启动和关闭"><a href="#Nginx的启动和关闭" class="headerlink" title="Nginx的启动和关闭"></a>Nginx的启动和关闭</h3><p>nginx -h 查看帮助信息<br>nginx -v 查看Nginnx的版本号<br>nginx -V 显示Nginx的版本号和编译信息<br>start nginx 启动Nginx<br><strong>nginx -s stop 快速停止和关闭Nginx</strong><br>nginx -s quit 正常停止或关闭Nginx<br><strong>nginx -s reload 配置文件修改重新加载</strong><br>nginx -t 测试Nginx配置文件的正确性及配置文件的详细信息<br>task/fi “imagename eq nginx.exe” windows命令框下查看Nginx的进程命令</p>
</blockquote>
<h2 id="5、常用指令操作："><a href="#5、常用指令操作：" class="headerlink" title="5、常用指令操作："></a>5、常用指令操作：</h2><blockquote>
<p>whereis  xxx:  用于检测某个文件或包是否存在；</p>
<p>ll  :   用于查看文件包的明细；</p>
<p><strong>进入到启动文件中：cd /usr/sbin  (可能需要root权限，可以通过“su root”+密码进行获得。)</strong></p>
</blockquote>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/05/10/Nginx&XShell%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Git学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/">Git学习</a>
    </h1>
  

        
        <a href="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-05-03T06:06:42.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-05-03</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="一、Git的部分使用："><a href="#一、Git的部分使用：" class="headerlink" title="一、Git的部分使用："></a>一、Git的部分使用：</h2><blockquote>
<p>1、如何将自己的项目，填充到Gitee上的已有项目包中：</p>
<blockquote>
<p>（1）获取到Gitee上的项目包地址，并通过“git clone”指令将文件clone到本地；</p>
</blockquote>
<blockquote>
<p>（2）将自己要补充的文件填充到项目包中；</p>
</blockquote>
<blockquote>
<p>（3）使用“git add .”(完成添加操作)→git status(查询添加状态)→“git commit  -m “更新了内容”→ “git push 分支名” ”等操作重新上传即可。</p>
</blockquote>
<p>2、git status 时报错： modified:   python_psy_pc (modified content, untracked content)</p>
<blockquote>
<h1 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h1></blockquote>
<blockquote>
<p>1、报错项目目录下有一个.git 目录，删除.git目录<br>2、重新git add .就可.</p>
</blockquote>
<p>3、如果想修改某个项目在Gitee上的所属仓库地址，可以：</p>
<blockquote>
<ul>
<li>一种：可以通过IDEA→VCS→Git→Remotes选项进行地址修改；</li>
<li>二种：删除该项目下的GITignore 与licesne文件；</li>
</ul>
</blockquote>
</blockquote>
<h2 id="二、IDEA使用Git"><a href="#二、IDEA使用Git" class="headerlink" title="二、IDEA使用Git:"></a>二、IDEA使用Git:</h2><p>大致流程：</p>
<p>（1）先在Gitee上创建一个将要用于存放托管代码的仓库；</p>
<p>​    <img src="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/Java_Projects\Blog\source\_posts\Git学习\操作1.jpg" alt="操作1" style="zoom: 50%;"></p>
<blockquote>
<p>（2）将新建仓库的地址clone到本地；</p>
<img src="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/Java_Projects\Blog\source\_posts\Git学习\操作2.jpg" alt="操作2" style="zoom:50%;">

<p>（3）将clone到本地的内容，复制并放到自己将要托管的项目当中；</p>
<p><img src="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/Users\FangBiao\AppData\Roaming\Typora\typora-user-images\image-20210503142331120.png"></p>
</blockquote>
<blockquote>
<p>（4）在IDEA中重新打开此项目，并调出Git操作图标；</p>
<p><img src="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/Users\FangBiao\AppData\Roaming\Typora\typora-user-images\image-20210503142742209.png" alt="image-20210503142742209"></p>
<p>（5）使用Git图标操作即可完成“add→commit→push”的操作；</p>
<p>（6）对于初次提交时，出现提交url时，填写Gitee中对应项目的url即可；</p>
<p>（7）操作过程中如果出现“push to origin/master was rejected”的问题，可以参考：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/wurendao/p/11732876.html%E3%80%82">https://www.cnblogs.com/wurendao/p/11732876.html。</a></p>
</blockquote>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/05/03/Git%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Java秋招学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/04/22/Java%E7%A7%8B%E6%8B%9B%E5%AD%A6%E4%B9%A0/">Java秋招学习</a>
    </h1>
  

        
        <a href="/2021/04/22/Java%E7%A7%8B%E6%8B%9B%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-04-22T07:54:44.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-04-22</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="一、Java基础知识："><a href="#一、Java基础知识：" class="headerlink" title="一、Java基础知识："></a>一、Java基础知识：</h1><h2 id="1、抽象类-amp-接口特点对比："><a href="#1、抽象类-amp-接口特点对比：" class="headerlink" title="1、抽象类&amp;接口特点对比："></a>1、抽象类&amp;接口特点对比：</h2><ul>
<li><h3 id="抽象类："><a href="#抽象类：" class="headerlink" title="抽象类："></a>抽象类：</h3></li>
</ul>
<p>特点:<br>1.抽象类中可以构造方法<br>2.抽象类中可以存在普通属性，方法，静态属性和方法。<br>3.抽象类中可以存在抽象方法。<br>4.<strong>如果一个类中有一个抽象方法，那么当前类一定是抽象类；抽象类中不一定有抽象方法。</strong><br>5.抽象类中的抽象方法，需要有子类实现，<strong>如果子类不实现，则子类也需要定义为抽象的。</strong><br>6,<strong>抽象类不能被实例化，抽象类和抽象方法必须被abstract修饰</strong></p>
<p>7.</p>
<blockquote>
<p>A：<strong>抽象类可以包含抽象方法</strong></p>
<p>B：类中定义成员和方法，<strong>不能直接进行运算，但可以写在代码块{}或者静态代码块中static{}中</strong></p>
<p>C: 与第四行想要构成重载，二者区别是返回类型，但是返回类型不能作为重载的依据</p>
<p>D: <strong>该方法使用abstract修饰，是抽象方法，但是他有方法体(带有{}的就是方法体，即使里面是空的)，就不能作为抽象方法.</strong></p>
</blockquote>
<p>关键字使用注意：<br>抽象类中的抽象方法（其前有abstract修饰）<strong>不能用private、static、synchronized、native访问修饰符修饰</strong>。</p>
<ul>
<li><h3 id="接口："><a href="#接口：" class="headerlink" title="接口："></a>接口：</h3></li>
</ul>
<p>1.在接口中只有方法的声明，没有方法体。<br>2.<strong>在接口中只有常量，因为定义的变量，在编译的时候都会默认加上public static final</strong><br>3.<strong>在接口中的方法，永远都被public来修饰</strong>。<br>4.<strong>接口中没有构造方法，也不能实例化接口的对象</strong>。（所以接口不能继承类）<br>5.接口可以实现多继承<br>6.<strong>接口中定义的方法都需要有实现类来实现，如果实现类不能实现接口中的所有方法则实现类定义为抽象类。</strong><br>7，接口可以继承接口，用extends.</p>
<blockquote>
<p>1.抽象类 不能被实例化 ( <strong>因为不具体，实例化没作用</strong> )， 注意 <strong>接口不是类， 不能实例化[ new] ，只能 new 它的 实现类</strong></p>
<p>2.抽象类可以实现接口</p>
<p>3.抽象类是用abstract修饰的</p>
<p>4.接口 默认访问权限为 public，而且<strong>只能使用 public</strong>.</p>
</blockquote>
<h2 id="2、内部类："><a href="#2、内部类：" class="headerlink" title="2、内部类："></a>2、内部类：</h2><p><strong>1. 静态内部类：</strong></p>
<p>  静态内部类本身可以访问<strong>外部的静态资源，包括静态私有资源</strong>。但是<strong>不能访问非静态资源</strong>，可以不依赖外部类实例而实例化。</p>
<p><strong>2. 成员内部类：</strong></p>
<p>  成员内部类本身<strong>可以访问外部的所有资源</strong>，但是自身不能定义静态资源，因为其<strong>实例化本身就还依赖着外部类</strong>。</p>
<p><strong>3. 局部内部类：</strong></p>
<ul>
<li><p>  <strong>局部内部类就像一个局部方法，不能被访问修饰符修饰，也不能被static修饰。</strong></p>
</li>
<li><p>  局部内部类<strong>只能访问所在代码块</strong>或者方法中**被定义为final(或abstract)**的局部变量。</p>
</li>
</ul>
<p><strong>4. 匿名内部类：</strong></p>
<blockquote>
<p>没有类名的内部类，不能使用class，extends和implements，没有构造方法。</p>
<p> 多用于GUI中的事件处理。</p>
<p> 不能定义静态资源。</p>
<p> 只能创建一个匿名内部类实例。</p>
<p> 一个匿名内部类<strong>一定是在new后面的，这个匿名类必须继承一个父类或者实现一个接口</strong>。</p>
<p>匿名内部类是局部内部类的特殊形式，所以局部内部类的所有限制对匿名内部类也有效。</p>
</blockquote>
<h2 id="3、自动拆装箱："><a href="#3、自动拆装箱：" class="headerlink" title="3、自动拆装箱："></a>3、自动拆装箱：</h2><p>示例：</p>
<blockquote>
<p>在jdk1.5之后，下列 java 程序输出结果为___true/true___。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&gt;int i&#x3D;0;</span><br><span class="line">&gt;Integer j &#x3D; new Integer(0);</span><br><span class="line">&gt;System.out.println(i&#x3D;&#x3D;j);</span><br><span class="line">&gt;System.out.println(j.equals(i));</span><br></pre></td></tr></table></figure>
</blockquote>
<p>思想：</p>
<blockquote>
<p>1、<strong>基本型和基本型封装型进行“==”运算符的比较</strong>，基本型封装型将会自动拆箱变为基本型后再进行比较，因此Integer(0)会自动拆箱为int类型再进行比较，显然返回true；<br>2、两个Integer类型进行“==”比较，<strong>如果其值在-128至127，那么返回true，否则返回false,</strong> 这跟Integer.valueOf()的缓冲对象有关，这里不进行赘述。<br>3、两个基本型的封装型进行equals()比较，首先<strong>equals()会比较类型，如果类型相同，则继续比较值</strong>，如果值也相同，返回true<br>4、基本型封装类型调用equals(),但是参数是基本类型，这时候，先会进行自动装箱，基本型转换为其封装类型，再进行3中的比较。</p>
</blockquote>
<h2 id="4、ClassLoader："><a href="#4、ClassLoader：" class="headerlink" title="4、ClassLoader："></a>4、ClassLoader：</h2><p>示例1：</p>
<blockquote>
<p>关于Java中的ClassLoader下面的哪些描述是<strong>错误</strong>的：( B D F )</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt;A.默认情况下，Java应用启动过程涉及三个ClassLoader: Boostrap, Extension, System</span><br><span class="line">&gt;B.一般的情况不同ClassLoader装载的类是不相同的，但接口类例外，对于同一接口所有类装载器装载所获得的类是相同的</span><br><span class="line">&gt;C.类装载器需要保证类装载过程的线程安全</span><br><span class="line">&gt;D.ClassLoader的loadClass在装载一个类时，如果该类不存在它将返回<span class="keyword">null</span></span><br><span class="line">&gt;E.ClassLoader的父子结构中，默认装载采用了父优先</span><br><span class="line">&gt;F.所有ClassLoader装载的类都来自CLASSPATH环境指定的路径</span><br></pre></td></tr></table></figure>
</blockquote>
<p>解释：</p>
<blockquote>
<p><strong>A. Java系统提供3种类加载器：**</strong>启动类加载器（Bootstrap ClassLoader） 扩展类加载器（Extension ClassLoader） 应用程序类加载器（Application ClassLoader）. A正确**</p>
<p>B.<strong>《深入理解Java虚拟机》</strong>P228：对于任意一个类，都需要<strong>由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性，每一个类加载器，都拥有一个独立的类名称空间</strong>。这句话可以表达得更通俗一些：比较两个类是否“相等”，只有在这两个类是由<strong>同一个类加载器加载的前提下才有意义</strong>，否则，即使这两个类来源于同一个Class文件，被同一个虚拟机加载，只要加载它们的类加载器不同，那么这两个类必定不相等。接口类是一种特殊类，因此对于<strong>同一接口不同的类装载器装载所获得的类是不相同</strong>的。<strong>B错误</strong></p>
<p>C. <strong>类只需加载一次</strong>就行，因此要保证类加载过程线程安全，防止类加载多次。C正确</p>
<p><strong>D.</strong> Java程序的类加载器采用<strong>双亲委派</strong>模型，实现双亲委派的代码集中在java.lang.ClassLoader的loadClass()方法中，此方法实现的大致逻辑是：<strong>先检查是否已经被加载，若没有加载则调用父类加载器的loadClass()方法</strong>，若父类加载器为空则<strong>默认使用启动类加载器作为父类加载器</strong>。如果父类加载失败，抛出<strong>ClassNotFoundException异常</strong>。D错误</p>
<p>E.<strong>双亲委派</strong>模型的工作过程：如果一个类加载器收到了类加载的请求，它首先<strong>不会自己去尝试加载这个类</strong>，而是把这个<strong>请求委派给父类加载器去完成</strong>，每一个层次的类加载器都是如此，<strong>因此所有的加载请求最终都应该传送到顶层的启动类加载器中</strong>，只有当父加载器反馈<strong>自己无法完成这个加载请求时，子加载器才会尝试自己去加载</strong>。E正确</p>
<p><strong>F.应用程序类加载器（Application ClassLoader）负责加载****</strong>用户类路径（ClassPath）上所指定的类库，不是所有的ClassLoader都加载此路径。F错误**</p>
</blockquote>
<ul>
<li><h3 id="1、理论："><a href="#1、理论：" class="headerlink" title="1、理论："></a>1、理论：</h3><blockquote>
<h3 id="引导类加载器（bootstrap-class-loader）："><a href="#引导类加载器（bootstrap-class-loader）：" class="headerlink" title="引导类加载器（bootstrap class loader）："></a>引导类加载器（bootstrap class loader）：</h3><p>它用来<strong>加载 Java 的核心库**</strong>，*<em>是用原生代码来实现的**</em>，<strong>并不继承自 java.lang.ClassLoader**</strong>。主要负责jdk_home/lib目录下的核心api 或 -Xbootclasspath 选项指定的jar包装入工作（其中的jdk_home是指配置jdk环境变量是java_home的配置路径，一般是jdk/jre所在目录）。</p>
<h3 id="扩展类加载器（extensions-class-loader）："><a href="#扩展类加载器（extensions-class-loader）：" class="headerlink" title="扩展类加载器（extensions class loader）："></a>扩展类加载器（extensions class loader）：</h3><p>它<strong>用来加载 Java 的扩展库</strong>。Java虚拟机的实现会<strong>提供一个扩展库目录</strong>，扩展类加载器在此目录里面查找并加载 Java 类，主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。</p>
<h3 id="系统类加载器（system-class-loader）："><a href="#系统类加载器（system-class-loader）：" class="headerlink" title="系统类加载器（system class loader）："></a>系统类加载器（system class loader）：</h3><p>它<strong>根据 Java 应用的类路径（CLASSPATH）来加载 Java 类</strong>。一般来说，Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。主要负责CLASSPATH/-Djava.class.path所指的目录下的类与jar包装入工作.</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tomcat为每个App创建一个Loader，里面保存着此WebApp的ClassLoader。需要加载WebApp下的类时，就取出ClassLoader来使用</span><br></pre></td></tr></table></figure>



</li>
</ul>
<h2 id="5、哈希："><a href="#5、哈希：" class="headerlink" title="5、哈希："></a>5、哈希：</h2><ul>
<li>  示例：</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">java8中，下面哪个类用到了解决哈希冲突的开放定址法：C</span><br><span class="line">A.LinkedHashSet</span><br><span class="line">B.HashMap</span><br><span class="line">C.ThreadLocal</span><br><span class="line">D.TreeMap</span><br></pre></td></tr></table></figure>

<p>ThreadLocalMap通过key（ThreadLocal类型）的hashcode来计算数组存储的索引位置i。如果<strong>i位置已经存储了对象，那么就往后挪一个位置依次类推，直到找到空的位置，再将对象存放</strong>。另外，在最后还需要判断一下当前的存储的对象个数是否已经超出了阈值（threshold的值）大小，如果<strong>超出了，需要重新扩充并将所有的对象重新计算位置</strong>。</p>
<ul>
<li>hashCode()方法和equals()方法的作用异同？</li>
</ul>
<blockquote>
<p>​    hashCode()方法和equals()方法的作用其实是一样的，<strong>在Java里都是用来对比两个对象是否相等一致。</strong></p>
<p>​    重写的equals()里一般比较的比较全面比较复杂，这样效率就比较低，而利用hashCode()进行对比，则只要生成一个hash值进行比较就可以了，效率很高。</p>
<p>​    <strong><em>那么hashCode()既然效率这么高为什么还要equals()呢******？</em></strong> 因为<strong>hashCode()并不是完全可靠</strong>，有时候不同的对象他们生成的hashcode也会一样（生成hash值得公式可能存在的问题），所以hashCode()只能说是<strong>大部分时候可靠，并不是绝对可靠</strong>，</p>
<p><strong>所以我们可以得出：</strong></p>
<p><strong>equals()相等的两个对象他们的hashCode()肯定相等，也就是用equals()对比是绝对可靠的。</strong></p>
<p><strong>hashCode()相等的两个对象他们的equal()不一定相等，也就是hashCode()不是绝对可靠的。</strong></p>
<p>所有对于需要大量并且快速的对比的话如果都用equals()去做显然效率太低，所以解决方式是，每当需要对比的时候，首先用hashCode()去对比，<strong>如果hashCode()不一样，则表示这两个对象肯定不相等</strong>（也就是不必再用equal()去再对比了）,**如果hashCode()相同，此时再对比他们的equals()**，如果equals()也相同，则表示这两个对象是真的相同了，这样既能大大提高了效率也保证了对比的绝对正确性！</p>
</blockquote>
<ul>
<li><p>解决哈希冲突常用的两种方法是：<strong>开放定址法和链地址法</strong>；在java.util.HashMap中，总体来说是使用的<strong>链地址法</strong>来解决冲突的。</p>
<blockquote>
<p><strong>开放定址法</strong>：当冲突发生时，使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找，直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止（若要插入，在探查到开放的地址，则可将待插入的新结点存人该地址单元）。查找时探查到开放的地址则表明表中无待查的关键字，即查找失败。 </p>
<p><strong>链地址法</strong>：将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m，则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点，均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。</p>
</blockquote>
</li>
</ul>
<h2 id="6、流程控制语句："><a href="#6、流程控制语句：" class="headerlink" title="6、流程控制语句："></a>6、流程控制语句：</h2><p><strong>java 的4类流程控制语句:</strong></p>
<blockquote>
<ol>
<li><strong>循环语句：while，for，do while</strong></li>
<li><strong>选择语句（分支语句）：if,switch</strong></li>
<li><strong>跳转语句：break,continue,break,label</strong></li>
<li><strong>异常处理语句：try catch finally，throw</strong></li>
</ol>
</blockquote>
<p>示例：</p>
<p>以下对<strong>选择语句</strong>描述错误的是(A）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">A 根据某一条件重复执行一部分代码直到满足终止条件为止</span><br><span class="line">B 可以根据条件控制程序流程，改变程序执行的顺序</span><br><span class="line">C 选择语句可以嵌套使用</span><br><span class="line">D 当条件满足时就会执行相应的语句</span><br></pre></td></tr></table></figure>



<h2 id="7、new-String-和赋值”-”的区别："><a href="#7、new-String-和赋值”-”的区别：" class="headerlink" title="7、new String()和赋值”=”的区别："></a>7、new String()和赋值”=”的区别：</h2><ul>
<li><p><strong>“test”是存放在常量池中的对象</strong>，<strong>常量池中不会存放相同的对象</strong>，new String(“test”)是<strong>存放在堆中的对象</strong>，<strong>即使内容相同也会创建不同的对象。</strong></p>
</li>
<li><p>常量池中包含代码中所定义的各种基本类型（如int、long等等）和对象型（如String及数组）的常量值还，还包含一些以文本形式出现的符号引用，比如：<br>　　类和接口的全限定名；<br>  　　字段的名称和描述符；<br>  　　方法和名称和描述符。<br><strong>常量池其实也就是一个内存空间，不同于使用new关键字创建的对象所在的堆空间。</strong></p>
</li>
<li><p>通过常量池创建的对象，<strong>若内容相同，则只会有一个</strong>，而通过new创建的则不管之前有没有创建过内容相同的都会在堆里新创建一个对象。</p>
</li>
</ul>
<h2 id="8、List"><a href="#8、List" class="headerlink" title="8、List:"></a>8、List:</h2><ul>
<li><h3 id="示例："><a href="#示例：" class="headerlink" title="示例："></a>示例：</h3></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ArrayList和LinkList的描述，下面说法错误的是？ D</span><br><span class="line">a. LinkedeList和ArrayList都实现了List接口</span><br><span class="line">b. ArrayList是可改变大小的数组，而LinkedList是双向链接串列</span><br><span class="line">c. LinkedList不支持高效的随机元素访问</span><br><span class="line">d. 在LinkedList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动；而在ArrayList的中间插入或删除一个元素的开销是固定的</span><br></pre></td></tr></table></figure>

<ul>
<li><h3 id="理论："><a href="#理论：" class="headerlink" title="理论："></a>理论：</h3></li>
</ul>
<blockquote>
<p>ArryList和LinkedList<strong>都实现了List接口</strong>，<strong>ArrayList的内存结构是数组</strong>，本质是顺序存储的线性表，插入和删除操作都<strong>会引起后续元素移动</strong>，<strong>效率低，但是随机访问效率高</strong></p>
<p>LinkedList的内存结构是<strong>双向链表存储</strong>的，链式存储结构<strong>插入和删除效率高，不需要移动</strong>，但是<strong>随机访问效率低，需要从头开始</strong>向后依次访问。</p>
</blockquote>
<h2 id="9、“-”和equals的区别："><a href="#9、“-”和equals的区别：" class="headerlink" title="9、“==”和equals的区别："></a><strong>9、“==”和equals的区别：</strong></h2><blockquote>
<p><strong>equals方法不能作用于基本数据类型的变量;</strong></p>
<p><strong>==</strong>  <strong>如果作用于基本数据类型的变量，则直接比较其存储的 “值”是否相等；</strong>如果作用于引用类型的变量，则比较的是所指向的对象的<strong>地址</strong>.</p>
</blockquote>
<ul>
<li><h3 id="示例：-1"><a href="#示例：-1" class="headerlink" title="示例："></a>示例：</h3><blockquote>
<p>执行下列程序的输出结果为（ <strong>s1 != s2;   s1 equals s2</strong>）</p>
<p>s1直接指向<strong>常量池中的字符串变量</strong>（没有就在常量池创建一个）; s2是指向<strong>堆里的一个字符串对象</strong>，对象里面有常量池中字符串对象的引用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"> &gt;<span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">String s1 = <span class="string">&quot;HelloWorld&quot;</span>;</span><br><span class="line">String s2 = <span class="keyword">new</span> String(<span class="string">&quot;HelloWorld&quot;</span>);</span><br><span class="line"><span class="keyword">if</span> (s1 == s2) &#123;</span><br><span class="line">System.out.println(<span class="string">&quot;s1 == s2&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">System.out.println(<span class="string">&quot;s1 != s2&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (s1.equals(s2)) &#123;</span><br><span class="line">System.out.println(<span class="string">&quot;s1 equals s2&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">System.out.println(<span class="string">&quot;s1 not equals s2&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</blockquote>
</li>
</ul>
<h2 id="10、线程部分："><a href="#10、线程部分：" class="headerlink" title="10、线程部分："></a><strong>10、线程部分：</strong></h2><blockquote>
<p>CountDownLatch 是<strong>等待一组线程执行完</strong>，才执行后面的代码。此时这组线程已经执行完。<br>CyclicBarrier 是<strong>等待一组线程至某个状态后</strong>再同时全部继续执行线程。此时这组线程还未执行完。</p>
</blockquote>
<h3 id="1）Join-函数："><a href="#1）Join-函数：" class="headerlink" title="1）Join()函数："></a>1）Join()函数：</h3><blockquote>
<p>join()的作用是：“主线程等待子线程终止”。也就是在子线程调用了<strong>join()方法后面的代码，只有等到子线程结束了才能执行。</strong></p>
</blockquote>
<ul>
<li><p>示例：</p>
<blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&gt;下列代码执行结果为（<span class="number">21</span>）</span><br><span class="line">&gt;<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String args[])</span><span class="keyword">throws</span> InterruptedException</span>&#123;</span><br><span class="line">          Thread t=<span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">              <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                  <span class="keyword">try</span> &#123;</span><br><span class="line">                      Thread.sleep(<span class="number">2000</span>);</span><br><span class="line">                  &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                      <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e);</span><br><span class="line">                  &#125;</span><br><span class="line">                  System.out.print(<span class="string">&quot;2&quot;</span>);</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;);</span><br><span class="line">          t.start();</span><br><span class="line">           </span><br><span class="line">          t.join();</span><br><span class="line">          System.out.print(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">      &#125;</span><br></pre></td></tr></table></figure>
</blockquote>
</li>
</ul>
<h3 id="2-多线程："><a href="#2-多线程：" class="headerlink" title="2)多线程："></a>2)多线程：</h3><h3 id="3-比较："><a href="#3-比较：" class="headerlink" title="3)比较："></a>3)比较：</h3><blockquote>
<p><strong>start是开启线程，run是线程的执行体，run是线程执行的入口。</strong></p>
<p>CyclicBarrier和CountDownLatch<strong>都可以让一组线程等待其他线程</strong>。<strong>前者是让一组线程相互等待到某一个状态再执行。后者是一个线程等待其他线程结束再执行。</strong></p>
<p>Callable中的call比Runnable中的run厉害<strong>就厉害在有返回值和可以抛出异常</strong>。同时这个返回值和线程池一起用的时候可以返回一个异步对象Future。</p>
<p>start是把线程从new变成了runnable</p>
</blockquote>
<h3 id="4）线程安全："><a href="#4）线程安全：" class="headerlink" title="4）线程安全："></a>4）线程安全：</h3><blockquote>
<p>线程安全的map:<strong>HashTable,\</strong>SynchronizedMap,**ConcurrentHashMap**<em>**</em></p>
<ul>
<li><p>Hashtable是线程安全的哈希表，它是通过synchronized来保证线程安全的；即，多线程通过同一个“对象的同步锁”来实现并发控制。Hashtable在线程竞争激烈时，效率比较低（此时建议使用ConcurrentHashMap）。当一个线程访问Hashtable的同步方法时，其它线程如果也在访问Hashtable的同步方法时，可能会进入阻塞状态。</p>
</li>
<li><p>Collections.synchronizedMap()使用了synchronized同步关键字来保证对Map的操作是线程安全的。</p>
</li>
<li><p>ConcurrentHashMap是线程安全的哈希表。在JDK1.7中它是通过“锁分段”来保证线程安全的，本质上也是一个“可重入的互斥锁”（ReentrantLock）。多线程对同一个片段的访问，是互斥的；但是，对于不同片段的访问，却是可以同步进行的。在JDK1.8中是通过使用CAS原子更新、volatile关键字、synchronized可重入锁实现的。</p>
</li>
</ul>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">以下哪些类是线程安全的（A D E）</span><br><span class="line">Vector</span><br><span class="line">HashMap</span><br><span class="line">ArrayList</span><br><span class="line">StringBuffer</span><br><span class="line">Properties</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">以下哪种方式实现的单例是线程安全的</span><br><span class="line">正确答案: A B C D   </span><br><span class="line">枚举;		静态内部类;		双检锁模式;		饿汉式</span><br></pre></td></tr></table></figure>



<h3 id="5-并发问题："><a href="#5-并发问题：" class="headerlink" title="5) 并发问题："></a>5) 并发问题：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">下列关于Java并发的说法中正确的是（B）</span><br><span class="line">A CopyOnWriteArrayList适用于写多读少的并发场景</span><br><span class="line">B ReadWriteLock适用于读多写少的并发场景</span><br><span class="line">C ConcurrentHashMap的写操作不需要加锁，读操作需要加锁</span><br><span class="line">D 只要在定义int类型的成员变量i的时候加上volatile关键字，那么多线程并发执行i++这样的操作的时候就是线程安全的了</span><br></pre></td></tr></table></figure>

<blockquote>
<ul>
<li><p>Volatite 只保证线程在“加载数据阶段”加载的数据是最新的，<strong>并不能保证线程安全</strong>。</p>
</li>
<li><p><strong>一个线程执行的过程有三个阶段：</strong>加载（复制）主存数据到操作栈 –&gt;  对操作栈数据进行修改  –&gt; 将操作栈数据写回主存</p>
</li>
<li><p>ReadWriteLock适用于读多写少的并发场景</p>
</li>
</ul>
</blockquote>
<h3 id="6）-线程转换："><a href="#6）-线程转换：" class="headerlink" title="6） 线程转换："></a>6） 线程转换：</h3><blockquote>
<p><strong>只有就绪态(可运行态)和运行态可以直接相互转换，其他都是单向的。</strong></p>
</blockquote>
<p><img src="/2021/04/22/Java%E7%A7%8B%E6%8B%9B%E5%AD%A6%E4%B9%A0/Users\FangBiao\AppData\Roaming\Typora\typora-user-images\image-20210504180139974.png" alt="image-20210504180139974"></p>
<h2 id="11、静态变量："><a href="#11、静态变量：" class="headerlink" title="11、静态变量："></a><strong>11、</strong>静态变量：</h2><ul>
<li>静态成员变量未被final时，它的值可以被更改；</li>
</ul>
<h2 id="12、垃圾回收机制："><a href="#12、垃圾回收机制：" class="headerlink" title="12、垃圾回收机制："></a><strong>12</strong>、垃圾回收机制：</h2><ul>
<li>并不是程序结束的时候进行<strong>GC(垃圾回收)**，GC的时间是不确定的，且GC的过程需要经过可达性分析，一个对象</strong>只有被标记两次**才会被GC。</li>
</ul>
<h2 id="13、Java理解："><a href="#13、Java理解：" class="headerlink" title="13、Java理解："></a><strong>13</strong>、Java理解：</h2><blockquote>
<p>Java是纯粹的面向对象语言，所有的方法都必须存在于类中,类才有封装，继承，多态的特性。.</p>
</blockquote>
<h3 id="其他："><a href="#其他：" class="headerlink" title="其他："></a>其他：</h3><blockquote>
<p><strong>关键字、保留字：</strong></p>
<p>1、<strong>null、true、false 是 Java 中的显式常量值</strong>，<strong>并不是关键字 或 保留字</strong></p>
<p>2、sizeof 是 C/C++ 中的方法，Java 中并没有这个方法，也没有该关键字 或 保留字</p>
<p>3、<strong>implements 和 instanceof 都是 Java 中的关键字</strong></p>
</blockquote>
<blockquote>
<p><strong>小数如果不加 f 后缀，默认是double类型。</strong>double转成float向下转换，意味着精度丢失，所以要进行强制类型转换。</p>
<p>‘f’ 字符会自动装箱成包装类，就可以向上转型成Object了。</p>
<p>整数默认是int类型，<strong>int类型不能转型为Double，最多通过自动装箱变为Integer</strong>但是Integer与Double没有继承关系，也没法进行转型。</p>
</blockquote>
<blockquote>
<p>for循环的三个都为空也是可以的 最简洁形式：for(;;;)</p>
<p>我们使用while 就是为了他的<strong>循环次数的不一定的</strong> 而for循环一般限定了循环次数；用while循环的语句可由for循环实现。</p>
</blockquote>
<blockquote>
<p>count = count++ 原理是 temp = count； count = count+1 ； count = temp；</p>
<p>即这个先将count这个的原值0暂存起来，然后count自加1变成1，最后将暂存的值赋值给count，count最终的值为0</p>
</blockquote>
<h3 id="1）java与C-的比较："><a href="#1）java与C-的比较：" class="headerlink" title="1）java与C++的比较："></a>1）java与C++的比较：</h3><ul>
<li><pre><code class="java">java和C++都有三个特征：封装、继承和多态
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">### 2)Java反射：</span><br><span class="line"></span><br><span class="line">&gt;Class类在java.lang包; Method, Filed,等，他们都在java.lang.reflet包下</span><br><span class="line">&gt;</span><br><span class="line">&gt;动态代理技术可以动态创建一个代理对象，反射不行</span><br><span class="line">&gt;</span><br><span class="line">&gt;**反射访问私有成员时，Field调用setAccessible可解除访问符限制**</span><br><span class="line">&gt;</span><br><span class="line">&gt;**CGLIB实现了字节码修改，反射不行**</span><br><span class="line">&gt;</span><br><span class="line">&gt;反射会动态创建额外的对象，比如每个成员方法只有一个Method对象作为root，他不胡直接暴露给用户。调用时会返回一个Method的包装类</span><br><span class="line">&gt;</span><br><span class="line">&gt;**反射带来的效率问题主要是动态解析类**，JVM没法对反射代码优化。</span><br><span class="line"></span><br><span class="line">### **3)四大修饰符：**</span><br><span class="line"></span><br><span class="line">&gt;\- private(私有的)</span><br><span class="line">&gt;**private可以修饰成员变量，成员方法，构造方法**，不能修饰类(此刻指的是外部类，内部类不加以考虑)。**被private修饰的成员只能在其修饰的本类中访问**，在其他类中不能调用，但是被private修饰的成员可以**通过set和get方法**向外界提供访问方式</span><br><span class="line">&gt;\- default(默认的)</span><br><span class="line">&gt;defalut即不写任何关键字，它可以修饰类，成员变量，成员方法，构造方法。被默认权限修饰后，其**只能被本类以及同包下的其他类访问**。</span><br><span class="line">&gt;\- protected(受保护的)</span><br><span class="line">&gt;protected可以修饰成员变量，成员方法，构造方法，但不能修饰类(此处指的是外部类，内部类不加以考虑)。**被protected修饰后，只能被同包下的其他类访问**。如果**不同包下的类要访问被protected修饰的成员，这个类必须是其子类**。</span><br><span class="line">&gt;\- public(公共的)</span><br><span class="line">&gt;public是权限最大的修饰符，他可以修饰类，成员变量，成员方法，构造方法。被public修饰后，可以再任何一个类中，不管同不同包，任意使用。</span><br><span class="line">&gt;</span><br><span class="line">&gt;| 作用域         | public | protected | default | private |</span><br><span class="line">&gt;| -------------- | ------ | --------- | ------- | ------- |</span><br><span class="line">&gt;| 同一个类       | √      | √         | √       | √       |</span><br><span class="line">&gt;| 同一个包       | √      | √         | √       |         |</span><br><span class="line">&gt;| 不同包里的子类 | √      | √         |         |         |</span><br><span class="line">&gt;| 不同包         | √      |           |         |         |</span><br><span class="line"></span><br><span class="line">### 4)构造函数：</span><br><span class="line"></span><br><span class="line">&gt;构造函数不能被继承，**构造方法只能被显式或隐式的调用**。</span><br><span class="line">&gt;</span><br><span class="line">&gt;构造函数**只能被调用**，不能被继承。子类默认调用父类无参构造器，若父类没有无参构造器，子类需要用super()调用父类有参构造器，且super()位于子类构造器的第一行。</span><br><span class="line">&gt;</span><br><span class="line">&gt;&#96;&#96;&#96;java</span><br><span class="line">&gt;子类不能继承父类的无参构造函数。</span><br><span class="line">&gt;子类可以在自己的构造函数中使用super关键字来调用父类的含参数构造函数，但这个调用语句必须是子类构造函数的第一个可执行语句。</span><br><span class="line">&gt;在创建子类的对象时，若不含带参构造函数，将先执行父类的无参构造函数，然后再执行自己的无参构造函数。</span><br></pre></td></tr></table></figure>
</code></pre>
</li>
</ul>
<h3 id="5）重载："><a href="#5）重载：" class="headerlink" title="5）重载："></a>5）重载：</h3><blockquote>
<p>重载要求：在同一个类中，有两个或两个以上的方法，</p>
<p>1、方法名一致；</p>
<p>2、<strong>形参列表不一致</strong>，即：形参个数不一致 或 形参类型不一致 或 不同类型的形参的顺序不一致（其中有一项不一样即可），并且与形参变量名是否相同无关；</p>
<p>3、方法<strong>返回值类型可以一样，也可以不一样</strong>。x`</p>
</blockquote>
<h3 id="6-java实例变量-局部变量-类变量和final变量的说法"><a href="#6-java实例变量-局部变量-类变量和final变量的说法" class="headerlink" title="6) java实例变量,局部变量,类变量和final变量的说法:"></a>6) java实例变量,局部变量,类变量和final变量的说法:</h3><blockquote>
<p>定义在类中的变量是类的成员变量，<strong>可以不进行初始化，Java会自动进行初始化</strong>，如果是引用类型默认初始化为null,如果是基本类型例如int则会默认初始化为0</p>
<p>局部变量是定义在方法中的变量，<strong>必须要进行初始化，否则不同通过编译</strong></p>
<p>被static关键字修饰的变量是静态的，<strong>静态变量随着类的加载而加载，所以也被称为类变量</strong></p>
<p>被final修饰发变量是常量</p>
</blockquote>
<h2 id="14、JSP问题："><a href="#14、JSP问题：" class="headerlink" title="14、JSP问题："></a>14、JSP问题：</h2><h3 id="1）一共有9个内置对象："><a href="#1）一共有9个内置对象：" class="headerlink" title="1）一共有9个内置对象："></a>1）一共有9个内置对象：</h3><blockquote>
<p>pageContext  javax.servlet.jsp.PageContext    // 表示页容器 EL表达式、 标签 、上传<br>request javax.servlet.http.HttpServletRequest  //服务器端取得客户端的信息：头信息 、Cookie 、请求参数 ，最大用处在MVC设计模式上<br>response javax.servlet.http.HttpServletResponse //服务器端回应客户端信息：Cookie、重定向<br>session javax.servlet.http.HttpSession //表示每一个用户，用于登录验证上<br>application javax.servlet.ServletContext  //表示<strong>整个服务器</strong><br>config javax.serlvet.ServletConfig  //取得初始化参数，初始化参数在web.xml文件中配置<br>exception java.lang.Throwable  //表示的是<strong>错误页的处理操作</strong><br>page java.lang.Object  //如同this一样，代表<strong>整个jsp页面自身</strong><br>out javax.servlet.jsp.JspWriter  //输出 ，但是尽量使用表达式输出</p>
</blockquote>
<h2 id="15、IO流理解："><a href="#15、IO流理解：" class="headerlink" title="15、IO流理解："></a>15、IO流理解：</h2><ul>
<li><p>示例：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">一个文件中的字符要写到另一个文件中，首先需要（C ）。程序逻辑：“先读后写”</span><br><span class="line">System.out.print (buffer[i]);</span><br><span class="line">FileOutputStream fout &#x3D; new FileOutputStream(this.filename);</span><br><span class="line">FileInputStream fin &#x3D; new FileInputStream(this.filename);。</span><br><span class="line">System.in.read(buffer)。</span><br></pre></td></tr></table></figure>

<blockquote>
<p>程序的逻辑很简单。程序必须打开两个文件，<strong>以可读的方式打开一个已有文件和以可写的方式打开一个新文</strong>件，后将已有文件中的内容，暂时存放在内存中，再写入新的文件，后关闭所有文件，程序结束。<br>根据题意，<strong>首先需要读入一个文件中的字</strong>符，需要FileInputStream fin = new FileInputStream(this.filename);</p>
</blockquote>
</li>
</ul>
<h2 id="16、异常处理问题："><a href="#16、异常处理问题：" class="headerlink" title="16、异常处理问题："></a>16、异常处理问题：</h2><blockquote>
<ul>
<li><p>异常处理的原则：<strong>先处理具体的异常</strong>，如果没有则放到一个大的范围之中Exception。(Exception为最大异常。)</p>
<p>eg:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ArithmeticException 是算数异常</span><br><span class="line">NumberFormatException 是数据格式异常</span><br><span class="line">Exception 异常</span><br><span class="line">ArrayIndexOutOfBoundException 数组索引超过界限异常</span><br><span class="line"></span><br><span class="line">先处理具体的异常，如果没有则放到一个大的范围之中Exception</span><br></pre></td></tr></table></figure>


</li>
</ul>
</blockquote>
<blockquote>
<p>Java的异常分为两种，<strong>一种是运行时异常（RuntimeException），一种是非运行异常也叫检查式异常（CheckedException</strong>）。</p>
<p>1、<strong>运行时异常</strong>不需要程序员去处理，<strong>当异常出现时，JVM会帮助处理</strong>。常见的运行时异常有：</p>
<p>ClassCastException(类转换异常)</p>
<p>ClassNotFoundException</p>
<p>IndexOutOfBoundsException(数组越界异常)</p>
<p>NullPointerException(空指针异常)</p>
<p>ArrayStoreException(数组存储异常，即数组存储类型不一致)</p>
<p>还有IO操作的BufferOverflowException异常</p>
<p>2、<strong>非运行异常</strong>需要程序员手动去捕获或者抛出异常进行显示的处理，因为Java认为Checked异常都是可以被修复的异常。常见的异常有：</p>
<p><strong>IOException</strong></p>
<p><strong>SqlException</strong></p>
</blockquote>
<h2 id="17、枚举问题："><a href="#17、枚举问题：" class="headerlink" title="17、枚举问题："></a><strong>17</strong>、枚举问题：</h2><ul>
<li>枚举类： 所有的枚举值都是类静态常量，在初始化时会对所有的枚举值对象进行第一次初始化。</li>
</ul>
<h2 id="18、程序理解问题："><a href="#18、程序理解问题：" class="headerlink" title="18、程序理解问题："></a><strong>18</strong>、程序理解问题：</h2><blockquote>
<ul>
<li>一个.java文件中定义多个类：</li>
</ul>
<p>注意一下几点：</p>
<p>(1) <strong>public权限类只能有一个</strong>（也可以一个都没有，但最多只有一个）；</p>
<p>(2)<strong>这个.java文件名只能是public 权限的类的类名</strong>；</p>
<p>(3)倘若这个文件中没有public 类，则它的.java文件的名字是随便的一个类名；</p>
<p>(4)<strong>当用javac命令生成编译这个.java 文件的时候，则会针对每一个类生成一个.class文件</strong>；</p>
</blockquote>
<h2 id="19、Socket编程："><a href="#19、Socket编程：" class="headerlink" title="19、Socket编程："></a><strong>19</strong>、Socket编程：</h2><p>（1）TCP客户端与TCP服务器端的操作过程：<strong>注意是由客户端发起连接过程Connect</strong>.</p>
<blockquote>
<p>TCP客户端： </p>
<p>1.建立连接套接字，设置Ip和端口监听，socket()</p>
<p>2.<strong>建立连接 connect</strong></p>
<p>3.write() 获取网络流对象 发送数据</p>
<p>4.read()获取网络流对象 接收数据</p>
<p>5.关闭套接字;</p>
<p>TCP服务器端</p>
<p>1.建立端口监听 socket()</p>
<p>2.绑定指定端口 bind()</p>
<p>3.listen 进行端口监听</p>
<p>4.accept() 阻塞式 直到有客户端访问</p>
<p>5.read()获取客户端发送数据</p>
<p>6.write()发送返回数据</p>
<p>7.close关闭端口监听</p>
</blockquote>
<h2 id="20、Java-Util工具类："><a href="#20、Java-Util工具类：" class="headerlink" title="20、Java.Util工具类："></a><strong>20</strong>、Java.Util工具类：</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">对Collection和Collections描述正确的是</span><br><span class="line">正确答案: B D   </span><br><span class="line">Collection是java.util下的类，它包含有各种有关集合操作的静态方法</span><br><span class="line">Collection是java.util下的接口，它是各种集合结构的父接口</span><br><span class="line">Collections是java.util下的接口，它是各种集合结构的父接口</span><br><span class="line">Collections是java.util下的类，它包含有各种有关集合操作的静态方法</span><br></pre></td></tr></table></figure>



<h1 id="二、计算机基础："><a href="#二、计算机基础：" class="headerlink" title="二、计算机基础："></a>二、计算机基础：</h1><h1 id="三、网络基础："><a href="#三、网络基础：" class="headerlink" title="三、网络基础："></a>三、网络基础：</h1><h1 id="四、数据库部分："><a href="#四、数据库部分：" class="headerlink" title="四、数据库部分："></a>四、数据库部分：</h1><h2 id="1、索引："><a href="#1、索引：" class="headerlink" title="1、索引："></a>1、索引：</h2><ul>
<li><p>MySQL组合索引（复合索引）的最左优先原则。最左优先就是说组合索引的第一个字段必须出现在查询组句中，这个索引才会被用到。只要组合索引最左边第一个字段出现在Where中，那么不管后面的字段出现与否或者出现顺序如何，MySQL引擎都会自动调用索引来优化查询效率。</p>
</li>
<li><p>带头大哥不能死，中间兄弟不能断！</p>
<ul>
<li><p>示例：</p>
<blockquote>
<p>有一个最左优先的原则，组合索引(a, b, c)，会建立三个索引, (a), (a, b), (a, b, c)。</p>
<p>在查询语句中，</p>
<p>1)where a = xxx </p>
<p>2)或者 where a = xxx and b = yyy</p>
<p>3)或者where a = xxx and b = yyy and c = zzz</p>
<p>4)或者 where b = yyy and c = zzz and a = xxx</p>
<p>都可以使用索引。第4）中情况可以优化成第3）种。</p>
<p><strong>不包含a的情况，则用不到索引</strong>。例如where b = yyy and c = zzz</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h1 id="五、设计模式部分："><a href="#五、设计模式部分：" class="headerlink" title="五、设计模式部分："></a>五、设计模式部分：</h1><h2 id="1、单例模式："><a href="#1、单例模式：" class="headerlink" title="1、单例模式："></a>1、单例模式：</h2><p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/happyone/p/11221157.html">Java面试必备：手写单例模式 - Java成魔之路 - 博客园 (cnblogs.com)</a></p>
<h3 id="为什么要有单例模式"><a href="#为什么要有单例模式" class="headerlink" title="为什么要有单例模式"></a>为什么要有单例模式</h3><blockquote>
<p>实际编程应用场景中，<strong>有一些对象其实我们只需要一个，比如线程池对象、缓存、系统全局配置对象等。</strong>这样可以就保证一个在全局使用的类不被频繁地创建与销毁，节省系统资源。</p>
</blockquote>
<h3 id="实现单例模式的几个要点"><a href="#实现单例模式的几个要点" class="headerlink" title="实现单例模式的几个要点"></a>实现单例模式的几个要点</h3><blockquote>
<ol>
<li>首先要确保全局只有一个类的实例。<br>要保证这一点，至少类的构造器要私有化。</li>
<li>单例的类只能自己创建自己的实例。<br>因为，构造器私有了，但是还要有一个实例，只能自己创建咯！</li>
<li>单例类必须能够提供自己的唯一实例给其他类<br>就是要有一个公共的方法能返回该单例类的唯一实例。</li>
</ol>
</blockquote>
<h3 id="单例模式的6种实现"><a href="#单例模式的6种实现" class="headerlink" title="单例模式的6种实现"></a>单例模式的6种实现</h3><h4 id="1、饿汉式—静态常量方式（线程安全，但会浪费空间）"><a href="#1、饿汉式—静态常量方式（线程安全，但会浪费空间）" class="headerlink" title="1、饿汉式—静态常量方式（线程安全，但会浪费空间）"></a>1、饿汉式—静态常量方式（线程安全，但会浪费空间）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;  </span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span> <span class="params">()</span></span>&#123;&#125;  	<span class="comment">//构造器私有</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Singleton instance = <span class="keyword">new</span> Singleton();  </span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">return</span> instance;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>类加载时就初始化实例，避免了多线程同步问题。天然线程安全。</p>
<h4 id="2、饿汉式—静态代码块方式（线程安全）"><a href="#2、饿汉式—静态代码块方式（线程安全）" class="headerlink" title="2、饿汉式—静态代码块方式（线程安全）"></a>2、饿汉式—静态代码块方式（线程安全）</h4><p>其实就是在上面 静态常量饿汉式 实现上稍微变动了一下，将类的实例化放在了静态代码块中而已。其他没区别。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Singleton instance;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        instance = <span class="keyword">new</span> Singleton();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="3、懒汉式（线程不安全）"><a href="#3、懒汉式（线程不安全）" class="headerlink" title="3、懒汉式（线程不安全）"></a>3、懒汉式（线程不安全）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Singleton singleton;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//当不存在时，才创建。</span></span><br><span class="line">        <span class="keyword">if</span> (singleton == <span class="keyword">null</span>) &#123;</span><br><span class="line">            singleton = <span class="keyword">new</span> Singleton();</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> singleton;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这是最基本的实现方式，<strong>第一次调用才初始化，实现了懒加载的特性</strong>。多线程场景下禁止使用，因为可能会产生多个对象，不再是单例。</p>
<h4 id="4、懒汉式（线程安全，方法上加同步锁）"><a href="#4、懒汉式（线程安全，方法上加同步锁）" class="headerlink" title="4、懒汉式（线程安全，方法上加同步锁）"></a>4、懒汉式（线程安全，方法上加同步锁）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Singleton singleton;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> Singleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (singleton == <span class="keyword">null</span>) &#123;</span><br><span class="line">            singleton = <span class="keyword">new</span> Singleton();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> singleton;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>和上面 懒汉式（线程不安全）实现上<strong>唯一不同是：获取实例的getInstance()方法上加了同步锁</strong>。保证了多线程场景下的单例。但是效率会有所折损，不过还好。</p>
<h4 id="5、双重校验锁（线程安全，效率高）"><a href="#5、双重校验锁（线程安全，效率高）" class="headerlink" title="5、双重校验锁（线程安全，效率高）"></a>5、双重校验锁（线程安全，效率高）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;</span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">static</span> Singleton singleton;</span><br><span class="line">	<span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    </span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getSingleton</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">if</span> (singleton == <span class="keyword">null</span>) &#123;</span><br><span class="line">			<span class="keyword">synchronized</span> (Singleton.class) &#123;</span><br><span class="line">				<span class="keyword">if</span> (singleton == <span class="keyword">null</span>) &#123;</span><br><span class="line">						singleton = <span class="keyword">new</span> Singleton();</span><br><span class="line">				&#125;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">return</span> singleton;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>双重校验：先校验该对象是否存在，不存在就需要创建；对类对象进行上锁。</p>
</blockquote>
<p><strong>此种实现中不用每次需要获得锁，减少了获取锁和等待的事件。</strong><br>注意<strong>volatile关键字</strong>的使用，<strong>保证了各线程对singleton静态实例域修改的可见性</strong>。</p>
<h4 id="6、静态内部类实现单例（线程安全、效率高）"><a href="#6、静态内部类实现单例（线程安全、效率高）" class="headerlink" title="6、静态内部类实现单例（线程安全、效率高）"></a>6、静态内部类实现单例（线程安全、效率高）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Singleton</span> </span>&#123;  </span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">SingletonHolder</span> </span>&#123;  </span><br><span class="line">    	<span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Singleton INSTANCE = <span class="keyword">new</span> Singleton();  </span><br><span class="line">    &#125;  </span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span> <span class="params">()</span></span>&#123;&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Singleton <span class="title">getInstance</span><span class="params">()</span> </span>&#123;  </span><br><span class="line">    	<span class="keyword">return</span> SingletonHolder.INSTANCE;  </span><br><span class="line">    &#125;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这种方式下 Singleton 类被装载了，instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用，只有通过显式调用 getInstance 方法时，才会显式装载 SingletonHolder 类，从而实例化 instance。<br>注意内部类SingletonHolder要用static修饰且其中的静态变量INSTANCE必须是final的。</p>
<h1 id="六、面试题体验："><a href="#六、面试题体验：" class="headerlink" title="六、面试题体验："></a>六、面试题体验：</h1><h2 id="（1）构成死锁的必要条件是什么？如何检测死锁，解除死锁？"><a href="#（1）构成死锁的必要条件是什么？如何检测死锁，解除死锁？" class="headerlink" title="（1）构成死锁的必要条件是什么？如何检测死锁，解除死锁？"></a>（1）构成死锁的必要条件是什么？如何检测死锁，解除死锁？</h2><blockquote>
<p><strong>必要条件：</strong></p>
<p> (1） 互斥条件：<strong>一个资源每次只能被一个进程使用</strong>。<br>（2） 请求与保持条件：一个进程因请求资源而阻塞时，对已获得的资源保持不放。（排队时，仍然拿着公共资源不放）<br>（3） 不剥夺条件:进程已获得的资源，在末使用完之前，不能强行剥夺。<br>（4） <strong>循环等待条件</strong>:若干进程之间形成一种头尾相接的循环等待资源关系。</p>
<p>有两个容器，一个用于保存线程正在请求的锁，一个用于保存线程已经持有的锁。<strong>每次加锁之前都会做如下检测</strong>:</p>
<p>（即当别的线程中使用的锁和自己持有的锁冲突时，表示出现了死锁。）</p>
<p>1)检测当前正在请求的锁是否已经被其它线程持有,如果有，则把那些线程找出来</p>
<p>2)遍历第一步中返回的线程，检查自己持有的锁是否正被其中任何一个线程请求</p>
<p>如果第二步返回真,表示出现了死锁。</p>
<p><strong>解除死锁：</strong></p>
<p>理解了死锁的原因，尤其是产生死锁的四个必要条件，就可以最大可能地避免、预防和<br>解除死锁。所以，<strong>在系统设计、进程调度等方面注意如何不让这四个必要条件成立</strong>，如何确<br>定资源的合理分配算法，避免进程永久占据系统资源。此外，也要防止进程在处于等待状态</p>
<p>的情况下占用资源。因此，对资源的分配要给予合理的规划。</p>
</blockquote>
<h2 id="（2）Java具有的特点："><a href="#（2）Java具有的特点：" class="headerlink" title="（2）Java具有的特点："></a>（2）Java具有的特点：</h2><blockquote>
<p>java特点包括<strong>简单性、面向对象</strong>、分布式、<strong>健壮性、安全性、平台独立与可移植性</strong>、<strong>多线程、动态性</strong>等;</p>
<p>java可以编写桌面应用程序、<strong>Web应用程序、分布式系统</strong>和嵌入式系统应用程序等。</p>
</blockquote>
<h2 id="3-何为IOC"><a href="#3-何为IOC" class="headerlink" title="(3) 何为IOC?"></a>(3) 何为IOC?</h2><blockquote>
<p>Ioc—Inversion of Control，即“控制反转”，不是什么技术，而是一种设计思想。在Java开发中，<strong>Ioc意味着将你设计好的对象交给容器控制，而不是传统的在你的对象内部直接控制</strong>。</p>
<ul>
<li><strong>谁控制谁，控制什么：</strong>传统Java SE程序设计，我们直接在对象内部通过new进行创建对象，是程序主动去创建依赖对象；而IoC是有专门一个容器来创建这些对象，即由Ioc容器来控制对象的创建；<strong>谁控制谁？当然是IoC 容器控制了对象；控制什么？那就是主要控制了外部资源获取（不只是对象包括比如文件等）</strong>。</li>
</ul>
<p>●<strong>为何是反转，哪些方面反转了：</strong>有反转就有正转，传统应用程序是由我们自己在对象中主动控制去直接获取<strong>依赖对象</strong>，也就是正转；而反转则是由容器来帮忙创建及注入依赖对象；为何是反转？因为由容器帮我们查找及注入依赖对象，对象只是被动的接受依赖对象，所以是反转；哪些方面反转了？依赖对象的获取被反转了。</p>
<p>特点：</p>
<blockquote>
<p>把<strong>创建和查找依赖对象的控制权交给了容器</strong>，由容器进行注入组合对象，所以<strong>对象与对象之间是松散耦合</strong>，这样也方便测试，利于功能复用，更重要的是使得程序的整个体系结构变得非常灵活。</p>
</blockquote>
<blockquote>
<p><strong>IOC 和DI：</strong></p>
<p>DI—Dependency Injection，即“依赖注入”：是<strong>组件之间依赖关系由容器在运行期决定</strong>，形象的说，即由<strong>容器动态的将某个依赖关系注入到组件之中</strong>。依赖注入的目的并非为软件系统带来更多功能，而是为了提升组件重用的频率，并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制，<strong>我们只需要通过简单的配置</strong>，而无需任何代码就可指定目标需要的资源，完成自身的业务逻辑，而不需要关心具体的资源来自何处，由谁实现。</p>
<p>理解DI的关键是：“谁依赖谁，为什么需要依赖，谁注入谁，注入了什么”，那我们来深入分析一下：</p>
<blockquote>
<p>●<strong>谁依赖于谁：</strong>当然是<strong>应用程序依赖于IoC容器</strong>；</p>
<p>●<strong>为什么需要依赖：</strong>应用程序需要IoC容器来<strong>提供对象需要的外部资源</strong>；</p>
<p>●<strong>谁注入谁：</strong>很明显是<strong>IoC容器注入应用程序某个对象，应用程序依赖的对象</strong>；</p>
<p><strong>●注入了什么：</strong>就是注入某个对象所需要的<strong>外部资源（包括对象、资源、常量数据）</strong>。</p>
</blockquote>
<p>IoC和DI由什么关系呢？其实它们是<strong>同一个概念的不同角度描述</strong>，由于控制反转概念比较含糊（可能只是理解为容器控制对象这一个层面，很难让人想到谁来维护对象关系），所以2004年大师级人物Martin Fowler又给出了一个新的名字：“依赖注入”，相对IoC 而言，<strong>“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。</strong></p>
</blockquote>
</blockquote>

      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/04/22/Java%E7%A7%8B%E6%8B%9B%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-MybBatisPlus-学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/">MybBatisPlus 学习</a>
    </h1>
  

        
        <a href="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-04-11T09:56:05.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-04-11</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <blockquote>
<p>MyBatisPlus 特性: </p>
</blockquote>
<ul>
<li><p><strong>无侵入</strong>：只做增强不做改变，引入它不会对现有工程产生影响，如丝般顺滑</p>
</li>
<li><p><strong>损耗小</strong>：启动即会自动注入基本 CURD，性能基本无损耗，直接面向对象操作</p>
</li>
<li><p><strong>强大的 CRUD 操作</strong>：内置通用 Mapper、通用 Service，仅仅通过少量配置即可实现单表大部分 CRUD 操作，更有强大的条件构造器，满足各类使用需求</p>
</li>
<li><p><strong>支持 Lambda 形式调用</strong>：通过 Lambda 表达式，方便的编写各类查询条件，无需再担心字段写错</p>
</li>
<li><p><strong>支持主键自动生成</strong>：支持多达 4 种主键策略（内含分布式唯一 ID 生成器 - Sequence），可自由配置，完美解决主键问题</p>
</li>
<li><p><strong>支持 ActiveRecord 模式</strong>：支持 ActiveRecord 形式调用，实体类只需继承 Model 类即可进行强大的 CRUD 操作</p>
</li>
<li><p><strong>支持自定义全局通用操作</strong>：支持全局通用方法注入（ Write once, use anywhere ）</p>
</li>
<li><p><strong>内置代码生成器</strong>：采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码，支持模板引擎，更有超多自定义配置等您来使用</p>
</li>
<li><p><strong>内置分页插件</strong>：基于 MyBatis 物理分页，开发者无需关心具体操作，配置好插件之后，写分页等同于普通 List 查询</p>
</li>
<li><p><strong>分页插件支持多种数据库</strong>：支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库</p>
</li>
<li><p><strong>内置性能分析插件</strong>：可输出 Sql 语句以及其执行时间，建议开发测试时启用该功能，能快速揪出慢查询</p>
</li>
<li><p><strong>内置全局拦截插件</strong>：提供全表 delete 、 update 操作智能分析阻断，也可自定义拦截规则，预防误操作</p>
</li>
</ul>
<h1 id="一、使用流程-部分介绍-："><a href="#一、使用流程-部分介绍-：" class="headerlink" title="一、使用流程(部分介绍)："></a>一、使用流程(部分介绍)：</h1><h2 id="1、在pom-xml中配置信息："><a href="#1、在pom-xml中配置信息：" class="headerlink" title="1、在pom.xml中配置信息："></a>1、在pom.xml中配置信息：</h2><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--mybatis_plus--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.baomidou&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;3.0.5&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<h2 id="2、在mapper文件中的UserMapper类中，只需要继承BaseMapper类，不需要写具体的CRUD操作语句。"><a href="#2、在mapper文件中的UserMapper类中，只需要继承BaseMapper类，不需要写具体的CRUD操作语句。" class="headerlink" title="2、在mapper文件中的UserMapper类中，只需要继承BaseMapper类，不需要写具体的CRUD操作语句。"></a>2、在mapper文件中的UserMapper类中，只需要继承BaseMapper类，不需要写具体的CRUD操作语句。</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.kingone.mapper;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.mapper.BaseMapper;</span><br><span class="line"><span class="keyword">import</span> com.kingone.pojo.User;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Repository;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*对于MybatisPlus,只需要写一个集成BaseMapper类的接口，其他的CRUD交给框架完成*/</span></span><br><span class="line"><span class="meta">@Repository</span> <span class="comment">//此注解用于表名当前的操作时DAO层的</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserMapper</span> <span class="keyword">extends</span> <span class="title">BaseMapper</span>&lt;<span class="title">User</span>&gt; </span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>注意：我们需要在主程序中通过“@MapperScan()”注解完成mapper的绑定</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@MapperScan(&quot;com.kingone.mapper&quot;)</span>   <span class="comment">/*此处是将该路径下的mapper全部扫描进来，方便后续操作*/</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MybatisPlusApplication</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SpringApplication.run(MybatisPlusApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</blockquote>
<h2 id="3、数据查询日志的使用："><a href="#3、数据查询日志的使用：" class="headerlink" title="3、数据查询日志的使用："></a>3、数据查询日志的使用：</h2><p>日志的配置：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 配置日志信息</span><br><span class="line">mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl</span><br></pre></td></tr></table></figure>

<p>测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*完成插入程序的测试*/</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testInsert</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">/*创建自己要添加的对象*/</span></span><br><span class="line">        User user = <span class="keyword">new</span> User();</span><br><span class="line">        user.setName(<span class="string">&quot;KingOne&quot;</span>);</span><br><span class="line">        user.setAge(<span class="number">23</span>);</span><br><span class="line">        user.setEmail(<span class="string">&quot;sere@qq.com&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> res = userMapper.insert(user);</span><br><span class="line">        System.out.println(res);    <span class="comment">//返回受影响的行数</span></span><br><span class="line">        System.out.println(user);   <span class="comment">//可以发现，id可以自动生成。</span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>结果：</p>
<img src="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/%E6%9F%A5%E8%AF%A2%E7%BB%93%E6%9E%9C.jpg" class>

<h2 id="4、主键生成策略："><a href="#4、主键生成策略：" class="headerlink" title="4、主键生成策略："></a>4、主键生成策略：</h2><ol>
<li><h3 id="生成ID的若干种方法：UUID、主键自增、redis生成ID、zookeeper"><a href="#生成ID的若干种方法：UUID、主键自增、redis生成ID、zookeeper" class="headerlink" title="生成ID的若干种方法：UUID、主键自增、redis生成ID、zookeeper"></a>生成ID的若干种方法：UUID、主键自增、redis生成ID、zookeeper</h3></li>
</ol>
<p>分布式系统唯一id的生成方法： <a target="_blank" rel="noopener" href="https://www.cnblogs.com/haoxinyue/p/5208136.html">https://www.cnblogs.com/haoxinyue/p/5208136.html</a></p>
<ol start="2">
<li><p>snowflake是Twitter开源的分布式ID生成算法，<strong>结果是一个long型的ID</strong>。其核心思想是：使用41bit作为毫秒数，10bit作为机器的ID（5个bit是数据中心，5个bit的机器ID），12bit作为毫秒内的流水号（意味着每个节点在每毫秒可以产生 4096 个 ID），最后还有一个符号位，永远是0。具体实现的代码可以参看<a target="_blank" rel="noopener" href="https://github.com/twitter/snowflake%E3%80%82">https://github.com/twitter/snowflake。</a></p>
</li>
<li><p>主键自增设置：</p>
<ul>
<li><p>1.在pojo文件的类对象上使用：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@TableId(type &#x3D; IdType.AUTO)    &#x2F;&#x2F;主键自增型</span><br></pre></td></tr></table></figure>
</li>
<li><p>设置数据库中为“主键自增”：</p>
<img src="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/%E4%B8%BB%E9%94%AE%E8%87%AA%E5%A2%9E%E8%AE%BE%E7%BD%AE.jpg" class>



</li>
</ul>
</li>
</ol>
<ol start="4">
<li><p>其他设置类型：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">public enum IdType &#123;</span><br><span class="line">    AUTO(0),	&#x2F;&#x2F;为主键自增类型</span><br><span class="line">    NONE(1),	&#x2F;&#x2F;未设置主键</span><br><span class="line">    INPUT(2),	&#x2F;&#x2F;手动输入</span><br><span class="line">    ID_WORKER(3),	&#x2F;&#x2F;默认的全局唯一id</span><br><span class="line">    UUID(4),	&#x2F;&#x2F;全局唯一id,</span><br><span class="line">    ID_WORKER_STR(5);	&#x2F;&#x2F;ID_WORKER的字符串表示</span><br><span class="line"></span><br><span class="line">    private int key;</span><br><span class="line"></span><br><span class="line">    private IdType(int key) &#123;</span><br><span class="line">        this.key &#x3D; key;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public int getKey() &#123;</span><br><span class="line">        return this.key;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



</li>
</ol>
<h2 id="5、自动填充："><a href="#5、自动填充：" class="headerlink" title="5、自动填充："></a>5、自动填充：</h2><p>对于我们更新数据库时，常常需要更新时间信息，可以通过自动填充实现。</p>
<p>(1)首先我们在实体类中使用相关注解。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">    <span class="comment">/*对于时间填充问题，可以采用如下策略：*/</span></span><br><span class="line">    <span class="meta">@TableField(fill = FieldFill.INSERT)</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//此处的更新应该包括插入时的创建时间</span></span><br><span class="line">    <span class="meta">@TableField(fill = FieldFill.INSERT_UPDATE)</span></span><br><span class="line">    <span class="keyword">private</span> Date updateTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>（2）写一个handler处理我们的注解请求：要注意@Component等部分。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">@Slf4j  &#x2F;&#x2F;用于该部分的日志打印操作</span><br><span class="line">@Component  &#x2F;&#x2F;将该部分放入到Spring容器中，才能识别与使用</span><br><span class="line">public class MyMetaObjectHandler implements MetaObjectHandler&#123;</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F;插入时的更新策略:在插入时，同时更新createTime属性和updateTime</span><br><span class="line">    @Override</span><br><span class="line">    public void insertFill(MetaObject metaObject) &#123;</span><br><span class="line">        &#x2F;&#x2F;日志操作部分</span><br><span class="line">        log.info(&quot;start insert fill&quot;);</span><br><span class="line"></span><br><span class="line">        &#x2F;&#x2F;执行其中的操作:要填充的对象属性，填充值，对象</span><br><span class="line">        this.setFieldValByName(&quot;createTime&quot;,new Date(),metaObject);</span><br><span class="line">        this.setFieldValByName(&quot;updateTime&quot;,new Date(),metaObject);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F;更新时的更新策略：在更新时，仅更新updateTime属性即可</span><br><span class="line">    @Override</span><br><span class="line">    public void updateFill(MetaObject metaObject) &#123;</span><br><span class="line">        log.info(&quot;start update fill&quot;);</span><br><span class="line"></span><br><span class="line">        this.setFieldValByName(&quot;updateTime&quot;,new Date(),metaObject);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="6、乐观锁："><a href="#6、乐观锁：" class="headerlink" title="6、乐观锁："></a>6、乐观锁：</h2><blockquote>
<p>乐观锁：即在任何时候都十分乐观，认为不会出现问题（即干什么都不会上锁）。当出现问题时，再次更新值测试。</p>
<p>悲观锁：即在任何时候都十分悲观，认为什么时候都可能出现问题（即干什么都会先上锁）。</p>
</blockquote>
<p>乐观锁实现方式：即对数据库的修改不上锁，且每修改一次会使得version更新一次。（但可能导致的事情是：某线程A正在对某一版本的数据库进行操作，但恰好被另一线程B抢先了，导致版本已经更新。从而A的全部操作失败。）</p>
<blockquote>
<ul>
<li>取出记录时，获取当前version</li>
<li>更新时，带上这个version</li>
<li>执行更新时， set version = newVersion where version = oldVersion</li>
<li>如果version不对，就更新失败</li>
</ul>
</blockquote>
<p><strong>乐观锁的理解：</strong></p>
<blockquote>
<p>Thread A:  获得的版本号： version =1</p>
<p>—-update语句：update +表名+  set +（变量名1 = “内容1”，变量名2 = “内容2”）  +where+  查询条件。</p>
<p>update user set name = ‘’kingone’’, version = version +1   <strong>where id=2 and version = 1.</strong></p>
<p>Thread B:   <strong>如果A的操作被B抢先完成，会是得version信息更新，从而使得A的操作失败。</strong></p>
<p>update user set name = ‘’kingone’’, version = version +1   <strong>where id=2 and version = 1.</strong></p>
</blockquote>
<p><strong>乐观锁的使用：</strong></p>
<p>（1）在实体类中加入该属性：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">    <span class="comment">/*在此处配置主键自增*/</span></span><br><span class="line">    <span class="comment">//@TableId(type = IdType.ID_WORKER)   //默认形式：全局唯一ID。</span></span><br><span class="line">    <span class="meta">@TableId(type = IdType.AUTO)</span>    <span class="comment">//主键自增型</span></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> String email;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Version</span>    <span class="comment">//使用mybatis中的注解，表示此处是乐观锁</span></span><br><span class="line">    <span class="keyword">private</span> Integer version;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*对于时间填充问题，可以采用如下策略：*/</span></span><br><span class="line">    <span class="meta">@TableField(fill = FieldFill.INSERT)</span></span><br><span class="line">    <span class="keyword">private</span> Date createTime;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//此处的更新应该包括插入时的创建时间</span></span><br><span class="line">    <span class="meta">@TableField(fill = FieldFill.INSERT_UPDATE)</span></span><br><span class="line">    <span class="keyword">private</span> Date updateTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(2)  编写配置类文件（注册组件）：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@MapperScan(&quot;com.kingone.mapper&quot;)</span></span><br><span class="line"><span class="meta">@EnableTransactionManagement</span>    <span class="comment">//开启事务管理</span></span><br><span class="line"><span class="meta">@Configuration</span>  <span class="comment">//表名是一个配置类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyBatisPlusConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//注册乐观锁插件</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> OptimisticLockerInterceptor <span class="title">optimisticLockerInterceptor</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> OptimisticLockerInterceptor();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(3)测试：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;测试乐观锁成功</span><br><span class="line">   @Test</span><br><span class="line">   public void testOptimisticLocker()&#123;</span><br><span class="line">       &#x2F;&#x2F;1.按序号查询信息</span><br><span class="line">       User user &#x3D; userMapper.selectById(1L);</span><br><span class="line">       &#x2F;&#x2F;2.对该信息进行修改</span><br><span class="line">       user.setName(&quot;King&quot;);</span><br><span class="line">       user.setAge(111);</span><br><span class="line">       &#x2F;&#x2F;3.执行更新操作</span><br><span class="line">       userMapper.updateById(user);</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   &#x2F;&#x2F;测试乐观锁失败：因为原本user先于user2，但最后执行更新操作时，是user2抢先执行.会导致user更新失败。</span><br><span class="line">   @Test</span><br><span class="line">   public void testOptimisticLocker2()&#123;</span><br><span class="line">       &#x2F;&#x2F;1.按序号查询信息</span><br><span class="line">       User user &#x3D; userMapper.selectById(1L);</span><br><span class="line">       &#x2F;&#x2F;2.对该信息进行修改</span><br><span class="line">       user.setName(&quot;King2&quot;);</span><br><span class="line">       user.setAge(111);</span><br><span class="line"></span><br><span class="line">       User user2 &#x3D; userMapper.selectById(1L);</span><br><span class="line">       &#x2F;&#x2F;2.对该信息进行修改</span><br><span class="line">       user2.setName(&quot;King3&quot;);</span><br><span class="line">       user2.setAge(11);</span><br><span class="line">       &#x2F;&#x2F;3.执行更新操作</span><br><span class="line">       userMapper.updateById(user2);</span><br><span class="line"></span><br><span class="line">       userMapper.updateById(user);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<img src="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/%E4%B9%90%E8%A7%82%E9%94%81%E9%AA%8C%E8%AF%81.jpg" class>

<blockquote>
<p>注意：在数据库中，应该为version设置默认值，并且确认显示成功（必要时，可以手动设置成默认值。）。否则会影响乐观锁的运行。</p>
</blockquote>
<h2 id="7、多种查询语句："><a href="#7、多种查询语句：" class="headerlink" title="7、多种查询语句："></a>7、多种查询语句：</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">contextLoads</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//1.此处实现全部查询，其中参数为条件：当为null时，查询全部信息</span></span><br><span class="line">        List&lt;User&gt; users = userMapper.selectList(<span class="keyword">null</span>);</span><br><span class="line">        users.forEach(System.out::println);     <span class="comment">//实现查询内容的遍历及打印</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*2.完成插入程序的测试*/</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testInsert</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">/*创建自己要添加的对象*/</span></span><br><span class="line">        User user = <span class="keyword">new</span> User();</span><br><span class="line">        user.setName(<span class="string">&quot;KingOne2&quot;</span>);</span><br><span class="line">        user.setAge(<span class="number">23</span>);</span><br><span class="line">        user.setEmail(<span class="string">&quot;sere@qq.com&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> res = userMapper.insert(user);</span><br><span class="line">        System.out.println(res);    <span class="comment">//返回受影响的行数</span></span><br><span class="line">        System.out.println(user);   <span class="comment">//可以发现，id可以自动生成。</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span>   <span class="comment">//3.测试更新操作：通过动态拼接sql语句实现</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testUpdate</span><span class="params">()</span></span>&#123;</span><br><span class="line">        User user = <span class="keyword">new</span> User();</span><br><span class="line">        user.setName(<span class="string">&quot;KingOne&quot;</span>);</span><br><span class="line">        user.setId(<span class="number">5L</span>);</span><br><span class="line">        user.setEmail(<span class="string">&quot;sere@qq.com&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//注意此处的updateById是一个对象。</span></span><br><span class="line">        userMapper.updateById(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//4.测试乐观锁成功</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testOptimisticLocker</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//1.按序号查询信息</span></span><br><span class="line">        User user = userMapper.selectById(<span class="number">1L</span>);</span><br><span class="line">        <span class="comment">//2.对该信息进行修改</span></span><br><span class="line">        user.setName(<span class="string">&quot;King&quot;</span>);</span><br><span class="line">        user.setAge(<span class="number">111</span>);</span><br><span class="line">        <span class="comment">//3.执行更新操作</span></span><br><span class="line">        userMapper.updateById(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//5.测试乐观锁失败</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testOptimisticLocker2</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//1.按序号查询信息</span></span><br><span class="line">        User user = userMapper.selectById(<span class="number">1L</span>);</span><br><span class="line">        <span class="comment">//2.对该信息进行修改</span></span><br><span class="line">        user.setName(<span class="string">&quot;King2&quot;</span>);</span><br><span class="line">        user.setAge(<span class="number">111</span>);</span><br><span class="line"></span><br><span class="line">        User user2 = userMapper.selectById(<span class="number">1L</span>);</span><br><span class="line">        <span class="comment">//2.对该信息进行修改</span></span><br><span class="line">        user2.setName(<span class="string">&quot;King3&quot;</span>);</span><br><span class="line">        user2.setAge(<span class="number">11</span>);</span><br><span class="line">        <span class="comment">//3.执行更新操作</span></span><br><span class="line">        userMapper.updateById(user2);</span><br><span class="line"></span><br><span class="line">        userMapper.updateById(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//6.测试查询语句</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectById</span><span class="params">()</span></span>&#123;</span><br><span class="line">        User user = userMapper.selectById(<span class="number">1</span>);</span><br><span class="line">        System.out.println(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//7.测试查询多组数据</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByBatchId</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//此处使用了数组工具类，将数组转换成了集合。</span></span><br><span class="line">        List&lt;User&gt; users = userMapper.selectBatchIds(Arrays.asList(<span class="number">1</span>, <span class="number">3</span>, <span class="number">4</span>));</span><br><span class="line">        System.out.println(users);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//8.测试条件查询 ：使用map存储查询条件</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testSelectByConditions</span><span class="params">()</span></span>&#123;</span><br><span class="line">        HashMap&lt;String, Object&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        <span class="comment">/*如果是多条件查询，则直接在map中添加多种键值对即可。*/</span></span><br><span class="line">        map.put(<span class="string">&quot;name&quot;</span>,<span class="string">&quot;KingOne&quot;</span>);     <span class="comment">//即查询条件为：name = &quot;King&quot;</span></span><br><span class="line">        map.put(<span class="string">&quot;age&quot;</span>,<span class="number">23</span>);</span><br><span class="line"></span><br><span class="line">        List&lt;User&gt; users = userMapper.selectByMap(map);</span><br><span class="line"></span><br><span class="line">        <span class="comment">/*下方为两种输出模式：直接按照users输出；另一种按照forEach()遍历输出*/</span></span><br><span class="line">       <span class="comment">// System.out.println(users);</span></span><br><span class="line">        users.forEach(System.out::println);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="8、使用分页助手实现分页查询："><a href="#8、使用分页助手实现分页查询：" class="headerlink" title="8、使用分页助手实现分页查询："></a>8、使用分页助手实现分页查询：</h2><p>（1）首先在config包中进行配置：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@MapperScan(&quot;com.kingone.mapper&quot;)</span></span><br><span class="line"><span class="meta">@EnableTransactionManagement</span>    <span class="comment">//开启事务管理</span></span><br><span class="line"><span class="meta">@Configuration</span>  <span class="comment">//表名是一个配置类</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyBatisPlusConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//分页插件：PageHelper</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> PaginationInterceptor <span class="title">paginationInterceptor</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> PaginationInterceptor();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(2) 使用过程：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">@Test</span><br><span class="line">    public void testPage()&#123;</span><br><span class="line">        &#x2F;*注意此处：通过实例化Page&lt;T&gt;()对象，设置查询页面条件（查询页，查询条数）；</span><br><span class="line">        * 然后通过usermapper中的方法进行查询：参数为（查询页面条件，查询条件）。*&#x2F;</span><br><span class="line">        Page&lt;User&gt; objectPage &#x3D; new Page&lt;&gt;(1,5);</span><br><span class="line">        IPage&lt;User&gt; users &#x3D; userMapper.selectPage(objectPage, null);</span><br><span class="line"></span><br><span class="line">       &#x2F;&#x2F; System.out.println(users);</span><br><span class="line">        objectPage.getRecords().forEach(System.out::println);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>（3）多种获取参数的方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">objectPage.getRecords();    <span class="comment">//获取所有记录数</span></span><br><span class="line">      System.out.println(objectPage.getCurrent());;    <span class="comment">//获取当前页面序号</span></span><br><span class="line">      System.out.println(objectPage.getSize());;       <span class="comment">//获取当前设置的查询大小</span></span><br><span class="line">      objectPage.getTotal();      <span class="comment">//获取纪录总条数</span></span><br><span class="line">      objectPage.hasNext();       <span class="comment">//查询是否有下一条</span></span><br><span class="line">      objectPage.hasPrevious();   <span class="comment">//查询是有前一条</span></span><br></pre></td></tr></table></figure>

<h2 id="9、删除操作："><a href="#9、删除操作：" class="headerlink" title="9、删除操作："></a>9、删除操作：</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//10.测试删除</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDeleteById</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//注意此处的参数为Long类型、。</span></span><br><span class="line">        <span class="keyword">int</span> i = userMapper.deleteById(<span class="number">1383742209072844811L</span>);</span><br><span class="line">        System.out.println(i);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//测试批量删除</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDeleteByBatchIds</span><span class="params">()</span></span>&#123;</span><br><span class="line">        userMapper.deleteBatchIds(Arrays.asList(<span class="number">2</span>,<span class="number">5</span>));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//11.通过map删除</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testDelByMap</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">//通过map设置删除条件</span></span><br><span class="line">        HashMap&lt;String, Object&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line">        map.put(<span class="string">&quot;name&quot;</span>,<span class="string">&quot;KingOne2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        userMapper.deleteByMap(map);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="10、逻辑删除："><a href="#10、逻辑删除：" class="headerlink" title="10、逻辑删除："></a>10、逻辑删除：</h2><blockquote>
<p>物理删除：从数据库中直接删除；</p>
<p>逻辑删除：在数据库中没有删除，而是通过一个变量让其失效而已。如：删除操作可以描述为：deleted=0 =&gt; deleted =1的变化。</p>
</blockquote>
<blockquote>
<p><strong>注意：逻辑删除真正的本质是更新deleted属性值，而非真正删除。</strong> </p>
<p>​          使用该注解后，在数据库底层是修改属性值，但查询时，会自动带出<strong>deleted条件</strong>。</p>
</blockquote>
<p>使用操作：</p>
<p>（1）现在数据库中添加“deleted”字段，表示删除状态。一般情况下，使用“deleted=0”表示未被删除。</p>
<p>（2）在实体列中添加“deleted”属性。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">@TableLogic &#x2F;&#x2F;逻辑删除注解，</span><br><span class="line">    private int deleted;</span><br></pre></td></tr></table></figure>

<p>（3）文件配置：</p>
<ul>
<li>在config中配置：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//3.使用逻辑删除组件</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ISqlInjector <span class="title">sqlInjector</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> LogicSqlInjector();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>在xml文件中配置：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 配置逻辑删除</span><br><span class="line">mybatis-plus.global-config.db-config.logic-delete-value=<span class="number">1</span></span><br><span class="line">mybatis-plus.global-config.db-config.logic-not-delete-value=<span class="number">0</span></span><br></pre></td></tr></table></figure>

</li>
</ul>
<p><strong>或者在最新版中使用如下配置</strong>：</p>
<p>如在yml文件中使用如下配置即可：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mybatis-plus:</span><br><span class="line">  global-config:</span><br><span class="line">    db-config:</span><br><span class="line">      logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)</span><br><span class="line">      logic-delete-value: 1 # 逻辑已删除值(默认为 1)</span><br><span class="line">      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)</span><br></pre></td></tr></table></figure>

<h2 id="11、性能分析（执行-SQL-分析打印）插件："><a href="#11、性能分析（执行-SQL-分析打印）插件：" class="headerlink" title="11、性能分析（执行 SQL 分析打印）插件："></a>11、性能分析（执行 SQL 分析打印）插件：</h2><p>在平时的开发中，需要针对部分查询较慢的SQL语句进行优化。</p>
<p>作用：性能分析拦截器，用于输出每条SQL语句及其执行时间。</p>
<p>使用：</p>
<ul>
<li><p>1、导入插件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">@MapperScan(&quot;com.kingone.mapper&quot;)</span><br><span class="line">@EnableTransactionManagement    &#x2F;&#x2F;开启事务管理</span><br><span class="line">@Configuration  &#x2F;&#x2F;表名是一个配置类</span><br><span class="line">public class MyBatisPlusConfig &#123;</span><br><span class="line"></span><br><span class="line">    &#x2F;&#x2F;1、配置性能分析（执行 SQL 分析打印）插件</span><br><span class="line">    @Bean</span><br><span class="line">    public PerformanceInterceptor performanceInterceptor()&#123;</span><br><span class="line">        PerformanceInterceptor performanceInterceptor &#x3D; new PerformanceInterceptor();</span><br><span class="line"></span><br><span class="line">        &#x2F;&#x2F;设置SQL执行的最大时间,如果超时，则不执行该语句。该语句可以用于找出超时的语句，以待改进。</span><br><span class="line">        performanceInterceptor.setMaxTime(100);</span><br><span class="line">        &#x2F;&#x2F;设置是否支持格式化</span><br><span class="line">        performanceInterceptor.setFormat(true);</span><br><span class="line"></span><br><span class="line">        return performanceInterceptor;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>2、修改proprties文件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 设置开发环境</span><br><span class="line">spring.profiles.active&#x3D;dev</span><br></pre></td></tr></table></figure>
</li>
<li><p>3、查询语句及结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">@Test</span><br><span class="line">    void contextLoads() &#123;</span><br><span class="line">        &#x2F;&#x2F;1.此处实现全部查询，其中参数为条件：当为null时，查询全部信息</span><br><span class="line">        List&lt;User&gt; users &#x3D; userMapper.selectList(null);</span><br><span class="line">        users.forEach(System.out::println);     &#x2F;&#x2F;实现查询内容的遍历及打印</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<img src="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/SQL%E6%89%A7%E8%A1%8C%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90.jpg" class>

</li>
</ul>
<h2 id="12、条件构造器："><a href="#12、条件构造器：" class="headerlink" title="12、条件构造器："></a>12、条件构造器：</h2><p>Wrapper：在wrapper中设置查询条件,然后将wrapper直接丢入到usermapper中使用。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">@SpringBootTest</span><br><span class="line">public class WrapperTests &#123;</span><br><span class="line"></span><br><span class="line">    @Autowired</span><br><span class="line">    private UserMapper userMapper;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">        &#x2F;&#x2F;查询name不为空，且邮箱信息不为空，年龄≥12的用户</span><br><span class="line">    void contextLoads() &#123;</span><br><span class="line">        QueryWrapper&lt;User&gt; wrapper &#x3D; new QueryWrapper&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        &#x2F;&#x2F;在wrapper中设置查询条件,然后将wrapper直接丢入到usermapper中。</span><br><span class="line">        &#x2F;&#x2F;大于：greater;小于：smaller&#x2F;less;等于：equal.</span><br><span class="line">        &#x2F;*1.此处的查询条件是：name&#x2F;email不为空；age在21岁及以上。*&#x2F;</span><br><span class="line">        wrapper</span><br><span class="line">                .isNotNull(&quot;name&quot;)</span><br><span class="line">                .isNotNull(&quot;email&quot;)</span><br><span class="line">                .ge(&quot;age&quot;,21);</span><br><span class="line">        userMapper.selectList(wrapper).forEach(System.out::println);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">        &#x2F;&#x2F;查询名字为Tom的用户</span><br><span class="line">    void test2()&#123;</span><br><span class="line">        QueryWrapper&lt;User&gt; wrapper &#x3D; new QueryWrapper&lt;&gt;();</span><br><span class="line">        &#x2F;*eq为相等、匹配条件*&#x2F;</span><br><span class="line">        wrapper.eq(&quot;name&quot;,&quot;Tom&quot;);</span><br><span class="line"></span><br><span class="line">        &#x2F;*此处为查询一个结果，如果出现多个结果则需要使用list&#x2F;map进行存储*&#x2F;</span><br><span class="line">        User user &#x3D; userMapper.selectOne(wrapper);</span><br><span class="line">        System.out.println(user);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">        &#x2F;&#x2F;查询年龄调价在20-25之间的用户</span><br><span class="line">    void test3()&#123;</span><br><span class="line">        QueryWrapper&lt;User&gt; wrapper &#x3D; new QueryWrapper&lt;&gt;();</span><br><span class="line">        wrapper.between(&quot;age&quot;,20,25);   &#x2F;&#x2F;查询区间为[20,25]</span><br><span class="line"></span><br><span class="line">        Integer nums &#x3D; userMapper.selectCount(wrapper); &#x2F;&#x2F;查询到的个数</span><br><span class="line">        System.out.println(userMapper.selectList(wrapper));</span><br><span class="line">        System.out.println(nums);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">        &#x2F;&#x2F;查询条件：name中不含有&quot;e&quot;,“m”右侧为模糊条件（以m开头）的信息</span><br><span class="line">    void test4()&#123;</span><br><span class="line">        QueryWrapper&lt;User&gt; wrapper &#x3D; new QueryWrapper&lt;&gt;();</span><br><span class="line">        wrapper</span><br><span class="line">                .notLike(&quot;name&quot;,&quot;e&quot;)    &#x2F;&#x2F;表示中间不含有“e”</span><br><span class="line">                .likeRight(&quot;name&quot;,&quot;m&quot;); &#x2F;&#x2F;从“m”之后进行模糊查询</span><br><span class="line"></span><br><span class="line">        List&lt;Map&lt;String, Object&gt;&gt; maps &#x3D; userMapper.selectMaps(wrapper);</span><br><span class="line">        System.out.println(maps);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">        &#x2F;&#x2F;测试子查询。即后面的查询条件是通过子查询获取到的</span><br><span class="line">    void Test5()&#123;</span><br><span class="line">        QueryWrapper&lt;User&gt; wrapper &#x3D; new QueryWrapper&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        &#x2F;&#x2F;id是从右侧的子查询中查询到的</span><br><span class="line">        wrapper.inSql(&quot;id&quot;,&quot;select id from user where id &#x3D;3&quot;);</span><br><span class="line">        List&lt;Object&gt; objects &#x3D; userMapper.selectObjs(wrapper);</span><br><span class="line"></span><br><span class="line">        System.out.println(objects);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">        &#x2F;&#x2F;查询结果为升降序排列</span><br><span class="line">    void Test6()&#123;</span><br><span class="line">        QueryWrapper&lt;User&gt; wrapper &#x3D; new QueryWrapper&lt;&gt;();</span><br><span class="line">        &#x2F;*Asc:为升序排列；Desc:为降序排列*&#x2F;</span><br><span class="line">        wrapper.orderByDesc(&quot;id&quot;);</span><br><span class="line"></span><br><span class="line">        System.out.println(userMapper.selectList(wrapper));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="13、代码自动生成器（反向构造）："><a href="#13、代码自动生成器（反向构造）：" class="headerlink" title="13、代码自动生成器（反向构造）："></a>13、代码自动生成器（反向构造）：</h2><p>  AutoGenerator 是 MyBatis-Plus 的代码生成器，通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码，极大的提升了开发效率。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.DbType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.FieldFill;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.IdType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.annotation.TableField;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.AutoGenerator;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.DataSourceConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.GlobalConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.PackageConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.StrategyConfig;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.po.TableFill;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.rules.DateType;</span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">KingCode</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//1.需要创建一个  代码自动生成器 对象</span></span><br><span class="line">        AutoGenerator generator = <span class="keyword">new</span> AutoGenerator();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.配置策略</span></span><br><span class="line">            <span class="comment">//2.1.全局配置</span></span><br><span class="line">        GlobalConfig gc = <span class="keyword">new</span> GlobalConfig();</span><br><span class="line">        String projectPath = System.getProperty(<span class="string">&quot;user.dir&quot;</span>);    <span class="comment">//存储路径</span></span><br><span class="line">        gc.setOutputDir(projectPath+<span class="string">&quot;/src/main/java&quot;</span>);      <span class="comment">//设置输出路径</span></span><br><span class="line">        gc.setAuthor(<span class="string">&quot;KingOne&quot;</span>);    <span class="comment">//设置作者信息</span></span><br><span class="line">        gc.setOpen(<span class="keyword">false</span>);      <span class="comment">//设置是否打开</span></span><br><span class="line">        gc.setFileOverride(<span class="keyword">false</span>);  <span class="comment">//设置是否文件覆盖</span></span><br><span class="line">        gc.setServiceName(<span class="string">&quot;%Service&quot;</span>);  <span class="comment">//去Service的前缀</span></span><br><span class="line">        gc.setIdType(IdType.ID_WORKER);     <span class="comment">//全局唯一id</span></span><br><span class="line">        gc.setDateType(DateType.ONLY_DATE);</span><br><span class="line">        gc.setSwagger2(<span class="keyword">true</span>);   <span class="comment">//Swagger用于前后端分离。</span></span><br><span class="line">            <span class="comment">//将全局配置策略放入到对象中</span></span><br><span class="line">        generator.setGlobalConfig(gc);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//2.2.设置数据源</span></span><br><span class="line">        DataSourceConfig dsc = <span class="keyword">new</span> DataSourceConfig();</span><br><span class="line">        dsc.setUrl(<span class="string">&quot;jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=Asia/Shanghai&amp;useUnicode=true&amp;characterEncoding=utf-8&quot;</span>);</span><br><span class="line">        dsc.setDriverName(<span class="string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>);</span><br><span class="line">        dsc.setUsername(<span class="string">&quot;root&quot;</span>);</span><br><span class="line">        dsc.setPassword(<span class="string">&quot;521FBHL521&quot;</span>);</span><br><span class="line">        dsc.setDbType(DbType.MYSQL);    <span class="comment">//设置数据库类型</span></span><br><span class="line">            <span class="comment">//将数据源配置策略放入到对象中</span></span><br><span class="line">        generator.setDataSource(dsc);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//2.3.包的配置</span></span><br><span class="line">        PackageConfig pc = <span class="keyword">new</span> PackageConfig();</span><br><span class="line">        pc.setModuleName(<span class="string">&quot;Blog&quot;</span>);   <span class="comment">//模块名</span></span><br><span class="line">        pc.setParent(<span class="string">&quot;com.Kuang&quot;</span>);</span><br><span class="line">        pc.setController(<span class="string">&quot;controller&quot;</span>);</span><br><span class="line">        pc.setEntity(<span class="string">&quot;entity&quot;</span>);   <span class="comment">//设置实体类名</span></span><br><span class="line">        pc.setMapper(<span class="string">&quot;mapper&quot;</span>);     <span class="comment">//mapper用于存储sql查询语句</span></span><br><span class="line">        pc.setService(<span class="string">&quot;service&quot;</span>);   <span class="comment">//service层</span></span><br><span class="line">            <span class="comment">//将包的配置策略放入到对象中</span></span><br><span class="line">        generator.setPackageInfo(pc);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//2.4.策略配置</span></span><br><span class="line">        StrategyConfig sc = <span class="keyword">new</span> StrategyConfig();</span><br><span class="line">        sc.setInclude(<span class="string">&quot;user_course&quot;</span>);  <span class="comment">//设置要映射的表名,需要和数据库中的表名对应</span></span><br><span class="line">        <span class="comment">/*2.4.1设置包、列的命名可以支持&quot;下划线转驼峰&quot;*/</span></span><br><span class="line">        sc.setNaming(NamingStrategy.underline_to_camel);</span><br><span class="line">        sc.setColumnNaming(NamingStrategy.underline_to_camel);</span><br><span class="line">        sc.setSuperEntityClass(<span class="string">&quot;自己的父类实体，没有时，可以不设置。&quot;</span>);</span><br><span class="line">        sc.setEntityLombokModel(<span class="keyword">true</span>);  <span class="comment">//自动开启lombok</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">/*2.4.2设置逻辑删除、自动填充等功能*/</span></span><br><span class="line">        sc.setLogicDeleteFieldName(<span class="string">&quot;deleted&quot;</span>);</span><br><span class="line">            <span class="comment">/*通过实例化TableFill对象，确定什么情况下的时间填充功能。*/</span></span><br><span class="line">        TableFill gmtCreate = <span class="keyword">new</span> TableFill(<span class="string">&quot;gmt_create&quot;</span>, FieldFill.INSERT);</span><br><span class="line">        TableFill gmtModify = <span class="keyword">new</span> TableFill(<span class="string">&quot;gmt_modify&quot;</span>, FieldFill.INSERT_UPDATE);</span><br><span class="line">            <span class="comment">/*当有多个tableFills时，需要先通过集合存储，在放入到配置中*/</span></span><br><span class="line">        ArrayList&lt;TableFill&gt; tableFills = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        tableFills.add(gmtCreate);</span><br><span class="line">        tableFills.add(gmtModify);</span><br><span class="line">        sc.setTableFillList(tableFills);</span><br><span class="line"></span><br><span class="line">        <span class="comment">/*2.4.3配置乐观锁*/</span></span><br><span class="line">        sc.setVersionFieldName(<span class="string">&quot;version&quot;</span>);</span><br><span class="line">        sc.setRestControllerStyle(<span class="keyword">true</span>);    <span class="comment">//开启Rest</span></span><br><span class="line">        sc.setControllerMappingHyphenStyle(<span class="keyword">true</span>);   <span class="comment">//支持驼峰命名转连字符，如：localhost:8080/h_id_2</span></span><br><span class="line"></span><br><span class="line">        generator.setStrategy(sc);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//3.执行</span></span><br><span class="line">        generator.execute();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>直接执行上述语句，即可自动生成Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码。</p>
</blockquote>
<h1 id="二、JPA的部分使用："><a href="#二、JPA的部分使用：" class="headerlink" title="二、JPA的部分使用："></a>二、JPA的部分使用：</h1><h2 id="1、创建entity包及操作对象："><a href="#1、创建entity包及操作对象：" class="headerlink" title="1、创建entity包及操作对象："></a>1、创建entity包及操作对象：</h2><blockquote>
<p>注意使用@Entity、@Data注解</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.persistence.Entity;</span><br><span class="line"><span class="keyword">import</span> javax.persistence.Id;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Entity</span>     <span class="comment">//使用此注解通过类名“book”和数据库中的“book”对应绑定</span></span><br><span class="line"><span class="meta">@Data</span>   <span class="comment">//自动生成getter setter</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Book</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Id</span></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String author;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="2、创建Repository包及数据库操作接口："><a href="#2、创建Repository包及数据库操作接口：" class="headerlink" title="2、创建Repository包及数据库操作接口："></a>2、创建Repository包及数据库操作接口：</h2><blockquote>
<p>注意JpaRepository&lt;Book,Integer&gt;分别表示：&lt;要操作的对象名，主键类型&gt;</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.kingone.springboottest.entity.Book;</span><br><span class="line"><span class="keyword">import</span> org.springframework.data.jpa.repository.JpaRepository;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*此处直接通过继承JpaRepositor对象，通过自带的方法完成查询*/</span></span><br><span class="line"><span class="comment">/*&lt;Book,Integer&gt;分别表示&lt;要操作的对象名，主键类型&gt;*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">BookRepository</span> <span class="keyword">extends</span> <span class="title">JpaRepository</span>&lt;<span class="title">Book</span>,<span class="title">Integer</span>&gt; </span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="3、考虑创建测试："><a href="#3、考虑创建测试：" class="headerlink" title="3、考虑创建测试："></a>3、考虑创建测试：</h2><blockquote>
<p>选中“BookRepository”接口，右键选择“转到”→”测试”，即可生成测试程序。</p>
<p>过程中注意@SpringBootTest、@AutoWired等注解的使用。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.junit.jupiter.api.Test;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">static</span> org.junit.jupiter.api.Assertions.*;</span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookRepositoryTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookRepository bookRepository;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">findAll</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(bookRepository.findAll());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/04/11/MybBatisPlus-%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-Vue学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/04/11/Vue%E5%AD%A6%E4%B9%A0/">Vue学习</a>
    </h1>
  

        
        <a href="/2021/04/11/Vue%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-04-11T07:08:38.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-04-11</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="一、Vue的基本安装与使用："><a href="#一、Vue的基本安装与使用：" class="headerlink" title="一、Vue的基本安装与使用："></a>一、Vue的基本安装与使用：</h1><h2 id="1、常见错误与解决导航："><a href="#1、常见错误与解决导航：" class="headerlink" title="1、常见错误与解决导航："></a>1、常见错误与解决导航：</h2><blockquote>
<h3 id="（1）Vue-cli2如何升级到3-0的问题："><a href="#（1）Vue-cli2如何升级到3-0的问题：" class="headerlink" title="（1）Vue-cli2如何升级到3.0的问题："></a>（1）Vue-cli2如何升级到3.0的问题：</h3><p><a target="_blank" rel="noopener" href="https://jingyan.baidu.com/article/0a52e3f46fffdbff62ed72da.html">https://jingyan.baidu.com/article/0a52e3f46fffdbff62ed72da.html</a></p>
</blockquote>
<h2 id="2、使用Tips："><a href="#2、使用Tips：" class="headerlink" title="2、使用Tips："></a>2、使用Tips：</h2><h3 id="1-Vue3-0以上版本与以下版本的运行项目方式与停止方式："><a href="#1-Vue3-0以上版本与以下版本的运行项目方式与停止方式：" class="headerlink" title="(1) Vue3.0以上版本与以下版本的运行项目方式与停止方式："></a>(1) Vue3.0以上版本与以下版本的运行项目方式与停止方式：</h3><blockquote>
<p>Vue3.0及以上的运行方式：npm run serve</p>
<p>Vue3.0以下的运行方式：npm run dev</p>
<p>停止Vue3.0项目的方式： <strong>ctrl + C;</strong></p>
</blockquote>
<h3 id="2-vue框架的主要构成："><a href="#2-vue框架的主要构成：" class="headerlink" title="(2) vue框架的主要构成："></a>(2) vue框架的主要构成：</h3><blockquote>
<ol>
<li>views文件夹主要用于放置每个页面组件；</li>
<li>router(路由)文件夹用于放置路由跳转信息；</li>
<li>main.js可以理解为容器，我们把需要使用的框架组件（router/Vue等）引入进来，同时绑定入口。</li>
<li>App.vue是SPA（单页富应用）的体现，此处的<template>标签放置的内容可以在全部页面中展示；<router-view>是完成根据不同的加载路径，完成对应页面内容的展示。</router-view></template></li>
<li></li>
</ol>
</blockquote>
<h3 id="3-更改Vue项目的端口号："><a href="#3-更改Vue项目的端口号：" class="headerlink" title="(3) 更改Vue项目的端口号："></a>(3) 更改Vue项目的端口号：</h3><blockquote>
<ul>
<li><h3 id="Vue-2-x"><a href="#Vue-2-x" class="headerlink" title="Vue 2.x:"></a>Vue 2.x:</h3></li>
</ul>
<p> <strong>config文件夹</strong>中有一个<code>index.js</code>其中部分内容如下，<code>port</code>即为端口号，在这里更改即可。</p>
 <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">module.exports &#x3D; &#123;</span><br><span class="line">    dev: &#123;</span><br><span class="line">        env: require(&#39;.&#x2F;dev.env&#39;),</span><br><span class="line">        port: 8080,    &#x2F;&#x2F; 端口号</span><br><span class="line">        assetsSubDirectory: &#39;static&#39;,</span><br><span class="line">        assetsPublicPath: &#39;&#x2F;&#39;,</span><br><span class="line">        proxyTable: &#123;&#125;,</span><br><span class="line">        &#x2F;&#x2F; CSS Sourcemaps off by default because relative paths are &quot;buggy&quot;</span><br><span class="line">        &#x2F;&#x2F; with this option, according to the CSS-Loader README</span><br><span class="line">        &#x2F;&#x2F; (https:&#x2F;&#x2F;github.com&#x2F;webpack&#x2F;css-loader#sourcemaps)</span><br><span class="line">        &#x2F;&#x2F; In our experience, they generally work as expected,</span><br><span class="line">        &#x2F;&#x2F; just be aware of this issue when enabling this option.</span><br><span class="line">        cssSourceMap: false,</span><br><span class="line">      &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<ul>
<li><h3 id="Vue-3-x"><a href="#Vue-3-x" class="headerlink" title="Vue 3.x:"></a>Vue 3.x:</h3><p>Vue 3.x中修改端口号则需要**在项目根目录(只能在src包下)**下创建一个<code>vue.config.js</code>，内容如下。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span>.<span class="keyword">exports</span> = &#123;</span><br><span class="line">    devServer: &#123;</span><br><span class="line">        port: <span class="number">8080</span>,     <span class="comment">// 端口号</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>


</li>
</ul>
</blockquote>
<h2 id="3、部分基础语法："><a href="#3、部分基础语法：" class="headerlink" title="3、部分基础语法："></a>3、部分基础语法：</h2><p>（1）多个数据的遍历：使用 <strong>v-for</strong>实现。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;tr v-for&#x3D;&quot;item in books&quot;&gt;</span><br><span class="line">                &lt;td&gt;&#123;&#123;item.id&#125;&#125;&lt;&#x2F;td&gt;</span><br><span class="line">                &lt;td&gt;&#123;&#123;item.name&#125;&#125;&lt;&#x2F;td&gt;</span><br><span class="line">                &lt;td&gt;&#123;&#123;item.author&#125;&#125;&lt;&#x2F;td&gt;</span><br><span class="line"> &lt;&#x2F;tr&gt;</span><br></pre></td></tr></table></figure>

<p>（2）当创建一个vue组件后，在调用时，需要完善router下的index.js：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue from <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> VueRouter from <span class="string">&#x27;vue-router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> Home from <span class="string">&#x27;../views/Home.vue&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Hello from <span class="string">&#x27;../views/Hello.vue&#x27;</span>	<span class="comment">//自己添加的需要跳转的vue组件</span></span><br><span class="line"></span><br><span class="line">Vue.use(VueRouter)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> routes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">&#x27;/&#x27;</span>,</span><br><span class="line">    name: <span class="string">&#x27;Home&#x27;</span>,</span><br><span class="line">    component: Home</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">&#x27;/about&#x27;</span>,</span><br><span class="line">    name: <span class="string">&#x27;About&#x27;</span>,</span><br><span class="line">    <span class="comment">// route level code-splitting</span></span><br><span class="line">    <span class="comment">// this generates a separate chunk (about.[hash].js) for this route</span></span><br><span class="line">    <span class="comment">// which is lazy-loaded when the route is visited.</span></span><br><span class="line">    component: () =&gt; <span class="keyword">import</span>(<span class="comment">/* webpackChunkName: &quot;about&quot; */</span> <span class="string">&#x27;../views/About.vue&#x27;</span>)</span><br><span class="line">  &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        path:<span class="string">&#x27;/hello&#x27;</span>,</span><br><span class="line">        component:Hello</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> VueRouter(&#123;</span><br><span class="line">  mode: <span class="string">&#x27;history&#x27;</span>,</span><br><span class="line">  base: process.env.BASE_URL,</span><br><span class="line">  routes</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">export <span class="keyword">default</span> router</span><br></pre></td></tr></table></figure>

<p>（3）Vue的生命周期：</p>
<blockquote>
<ul>
<li>一般vue使用ajax或者axios来获取后端数据，并且好像放在<strong>created</strong>里面和mounted里面都可以获取数据并正确渲染.</li>
</ul>
</blockquote>
<h2 id="4、使用中的错误及技术解决："><a href="#4、使用中的错误及技术解决：" class="headerlink" title="4、使用中的错误及技术解决："></a>4、使用中的错误及技术解决：</h2><p>（1）在使用axios时，<strong>出现“axios is not defined”的错误</strong>，可以参考：<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_39946015/article/details/105117645">(4条消息) 解决‘axios is not defined’_一点一滴成长的博客-CSDN博客</a>，重点在于“在main.js中引入axios”:  <strong>“import axios from ‘./plugins/axios”</strong></p>
<p>(2)</p>
<h1 id="二、Vue-SpringBoot项目："><a href="#二、Vue-SpringBoot项目：" class="headerlink" title="二、Vue+SpringBoot项目："></a>二、Vue+SpringBoot项目：</h1><h2 id="1、使用Vue创建前端部分："><a href="#1、使用Vue创建前端部分：" class="headerlink" title="1、使用Vue创建前端部分："></a>1、使用Vue创建前端部分：</h2><p>（1）先使用vue脚手架创建一个前端项目：</p>
<blockquote>
<p>先通过Git Bash创建一个前端的网页，且有对应的端口号（默认为8000）；</p>
</blockquote>
<p>代码为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue ui</span><br></pre></td></tr></table></figure>

<p>(2)通过端口号直接进入到VUE页面，通过此处进行项目创建等；</p>
<p>（3）通过“创建”选项，选择创建的地址后，即可设置相关选项；</p>
<blockquote>
<ul>
<li>初始化git仓库，可以选择“取消”；“预设”选项选择“手动配置”；</li>
<li>“选择功能”除了默认的设置外，可以勾选“Router”、“Vuex”，同时取消“Formatter”选项；</li>
<li>在“历史记录”选项中，选择打开此选项；</li>
<li>“预设名”中不设置，同时不保存为模板</li>
</ul>
</blockquote>
<p>(4)创建成功后，会出现一个“项目仪表盘”的成功页面；</p>
<p>​    此时通过“任务”→“server”→“运行”选项，执行我们的vue项目。在“输出”选项可以通过生成的网址进入。</p>
<p>（5）测试成功后，通过“Ctrl+C”关闭任务创建，在IDEA中进行开发即可。</p>
<h2 id="2、IDEA进行项目前端开发："><a href="#2、IDEA进行项目前端开发：" class="headerlink" title="2、IDEA进行项目前端开发："></a>2、IDEA进行项目前端开发：</h2><h3 id="（1）进入到IDEA打开之前的创建的项目即可；"><a href="#（1）进入到IDEA打开之前的创建的项目即可；" class="headerlink" title="（1）进入到IDEA打开之前的创建的项目即可；"></a>（1）进入到IDEA打开之前的创建的项目即可；</h3><blockquote>
<p>进入到项目后，如果发现main.js中出现报错问题，可以考虑在设置→语言&amp;框架→<strong>Java Script的语言版本，更改为“ECMAScript6</strong>”即可。</p>
</blockquote>
<blockquote>
<p>在IDEA中启动项目的方法：  在Terminal终端中输入<strong>“npm run serve”</strong>进行启动。</p>
</blockquote>
<h3 id="（2）Vue创建的项目架构："><a href="#（2）Vue创建的项目架构：" class="headerlink" title="（2）Vue创建的项目架构："></a>（2）Vue创建的项目架构：</h3><ul>
<li><p>views 视图层：此处是所有相关的跳转页面；</p>
<ul>
<li>view.vue组件的架构如下：分别对应HTML、JavaScript、CSS三部分内容</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;!--用于完成HTML的内容展示--&gt;</span><br><span class="line">    &lt;div&gt;   &lt;!--此处只能有一个主div标签，其他只能出现在其内部--&gt;</span><br><span class="line">    	&lt;div&gt; &lt;&#x2F;div&gt;</span><br><span class="line">    &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">    &#x2F;*完成javaScript部分内容：如json内容的放置*&#x2F;</span><br><span class="line">    export default &#123;</span><br><span class="line">        name: &quot;book&quot;,</span><br><span class="line">        &#x2F;&#x2F;json数据的放置</span><br><span class="line">        data() &#123;</span><br><span class="line">            return &#123;</span><br><span class="line">                msg:&#39;hello&#39;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">    &#x2F;*可完成CSS的内容*&#x2F;</span><br><span class="line">&lt;&#x2F;style&gt;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>在使用时：</p>
<blockquote>
</blockquote>
</li>
</ul>
</li>
<li><p>router路由层： 实现路由跳转信息的设置</p>
<blockquote>
<p>注意：</p>
<ul>
<li>在使用router路由时，需要将可能使用到路由的views层的页面引入进来；</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt;import Vue from &#39;vue&#39;</span><br><span class="line">&gt;import VueRouter from &#39;vue-router&#39;</span><br><span class="line"></span><br><span class="line">&gt;&#x2F;*引入需要设置路由的组件*&#x2F;</span><br><span class="line">&gt;import Home from &#39;..&#x2F;views&#x2F;Home.vue&#39;</span><br><span class="line">&gt;import About from &#39;..&#x2F;views&#x2F;About.vue&#39;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>再配置路由跳转信息：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">const routes &#x3D; [</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#39;&#x2F;&#39;,</span><br><span class="line">    name: &#39;Home&#39;,</span><br><span class="line">    component: Home</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    path: &#39;&#x2F;about&#39;,</span><br><span class="line">    name: &#39;About&#39;,</span><br><span class="line">    &#x2F;&#x2F; route level code-splitting</span><br><span class="line">    &#x2F;&#x2F; this generates a separate chunk (about.[hash].js) for this route</span><br><span class="line">    &#x2F;&#x2F; which is lazy-loaded when the route is visited.</span><br><span class="line">    component: () &#x3D;&gt; import(&#x2F;* webpackChunkName: &quot;about&quot; *&#x2F; &#39;..&#x2F;views&#x2F;About.vue&#39;)</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
</li>
</ul>
</blockquote>
</li>
</ul>
<h3 id="（3）vue将后端数据的获取与渲染："><a href="#（3）vue将后端数据的获取与渲染：" class="headerlink" title="（3）vue将后端数据的获取与渲染："></a>（3）vue将后端数据的获取与渲染：</h3><h2 id="3、使用IDEA创建SpringBoot后端项目："><a href="#3、使用IDEA创建SpringBoot后端项目：" class="headerlink" title="3、使用IDEA创建SpringBoot后端项目："></a>3、使用IDEA创建SpringBoot后端项目：</h2><h3 id="流程："><a href="#流程：" class="headerlink" title="流程："></a>流程：</h3><ul>
<li><p>使用“Spring inital”进行创建；</p>
</li>
<li><p>依赖文件的选用：</p>
<blockquote>
<p>常用项：</p>
<p>Develop Tools(LomBok)、Web(Spring Web)、SQL(JPA、MySQL Driver)等</p>
</blockquote>
</li>
</ul>
<p>（1）创建成功后，配置yml文件,参考如下（DataSource+jpa+server）：</p>
<blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&gt;spring:</span><br><span class="line"> datasource:</span><br><span class="line">   driver-class-name: com.mysql.cj.jdbc.Driver</span><br><span class="line">   username: root</span><br><span class="line">   password: 521FBHL521</span><br><span class="line">   url: jdbc:mysql:&#x2F;&#x2F;localhost:3306&#x2F;library?serverTimezone&#x3D;UTC&amp;useUnicode&#x3D;true&amp;characterEncoding&#x3D;utf-8</span><br><span class="line"></span><br><span class="line"> jpa:</span><br><span class="line">   show-sql: true</span><br><span class="line">   properties:</span><br><span class="line">     hibernate:</span><br><span class="line">       format_sql: true</span><br><span class="line"></span><br><span class="line">&gt;server:</span><br><span class="line"> port: 8181</span><br></pre></td></tr></table></figure>
</blockquote>
<p>（2）创建用到的实体类entity：<strong>注意@Entity   @Data注解</strong></p>
<p><strong>注意：此处创建的实体类的命名需要和数据库的表名进行严格对应。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.persistence.Entity;</span><br><span class="line"><span class="keyword">import</span> javax.persistence.Id;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Entity</span>     <span class="comment">//使用此注解通过类名“book”和数据库中的“book”对应绑定</span></span><br><span class="line"><span class="meta">@Data</span>   <span class="comment">//自动生成getter setter</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Book</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Id</span></span><br><span class="line">    <span class="meta">@GeneratedValue(strategy = GenerationType.IDENTITY)</span></span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String author;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(3) 写数据库操作接口Repository: <strong>注意JpaRepository&lt;Book,Integer&gt;的使用</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">import com.kingone.springboottest.entity.Book;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaRepository;</span><br><span class="line"></span><br><span class="line">&#x2F;*此处直接通过继承JpaRepositor对象，通过自带的方法完成查询*&#x2F;</span><br><span class="line">&#x2F;*&lt;Book,Integer&gt;分别表示&lt;要操作的对象名，主键类型&gt;*&#x2F;</span><br><span class="line">public interface BookRepository extends JpaRepository&lt;Book,Integer&gt; &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>(4)进行测试（可以省略）：<strong>对于在update操作时，注意get()方法的使用。</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">import org.junit.jupiter.api.Test;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.boot.test.context.SpringBootTest;</span><br><span class="line"></span><br><span class="line">import static org.junit.jupiter.api.Assertions.*;</span><br><span class="line"></span><br><span class="line">@SpringBootTest</span><br><span class="line">class BookRepositoryTest &#123;</span><br><span class="line"></span><br><span class="line">    @Autowired</span><br><span class="line">    private BookRepository bookRepository;</span><br><span class="line"></span><br><span class="line">    @Test</span><br><span class="line">    void findAll()&#123;</span><br><span class="line">        System.out.println(bookRepository.findAll());</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    @Test</span><br><span class="line">    void update()&#123;</span><br><span class="line">        &#x2F;*对于修改语句，一般是先通过id查到该对象后，再修改对象中的内容后，执行保存。*&#x2F;</span><br><span class="line">        Book book &#x3D; bookRepository.findById(2).get();</span><br><span class="line">        buyerAddress.setName(&quot;小王&quot;);</span><br><span class="line"></span><br><span class="line">        bookRepository.save(book);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>（5）配置controller层：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span> <span class="comment">//使用restful风格的controller注解，可以省去@ReposeBody注解</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/book&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BookHandler</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookRepository bookRepository;  <span class="comment">//其中含有数据操作对象</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/findAll&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Book&gt; <span class="title">findAll</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> bookRepository.findAll();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>此时启动后端应用，并通过端口访问出来的结果应该是JSON数据。因此下面考虑将JSON数据传给前端，并进行渲染。</p>
<h3 id="数据渲染时，VUE的工作："><a href="#数据渲染时，VUE的工作：" class="headerlink" title="数据渲染时，VUE的工作："></a>数据渲染时，VUE的工作：</h3><p>（1）首先安装axios异步查询的组件：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue add axios</span><br></pre></td></tr></table></figure>

<p>(2)完成安装后，进入要操作对象的vue组件的<script>中获取数据：<strong>重点在created()部分</strong></p>
<blockquote>
<p>涉及的语法：</p>
<p>/<em>查询后端内容的语法</em>/<br>           axios.get(‘<a target="_blank" rel="noopener" href="http://localhost:8181/book/findAll&#39;).then">http://localhost:8181/book/findAll&#39;).then</a>(function (resp) {<br>               console.log(resp)<br>           })</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;!--用于完成HTML的内容展示--&gt;</span><br><span class="line">    &lt;div&gt;   &lt;!--此处只能有一个div标签--&gt;</span><br><span class="line">        &lt;table&gt;</span><br><span class="line">            &lt;tr&gt;</span><br><span class="line">                &lt;td&gt;编号&lt;&#x2F;td&gt;</span><br><span class="line">                &lt;td&gt;图书名称&lt;&#x2F;td&gt;</span><br><span class="line">                &lt;td&gt;作者&lt;&#x2F;td&gt;</span><br><span class="line">            &lt;&#x2F;tr&gt;</span><br><span class="line">            &lt;tr v-for&#x3D;&quot;item in books&quot;&gt;</span><br><span class="line">                &lt;td&gt;&#123;&#123;item.id&#125;&#125;&lt;&#x2F;td&gt;</span><br><span class="line">                &lt;td&gt;&#123;&#123;item.name&#125;&#125;&lt;&#x2F;td&gt;</span><br><span class="line">                &lt;td&gt;&#123;&#123;item.author&#125;&#125;&lt;&#x2F;td&gt;</span><br><span class="line">            &lt;&#x2F;tr&gt;</span><br><span class="line">        &lt;&#x2F;table&gt;</span><br><span class="line">       &lt;!-- &#123;&#123;msg&#125;&#125;--&gt;</span><br><span class="line">    &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">    &#x2F;*完成javaScript部分内容：如json内容的放置*&#x2F;</span><br><span class="line">    export default &#123;</span><br><span class="line">        name: &quot;book&quot;,</span><br><span class="line">        data() &#123;</span><br><span class="line">            return &#123;</span><br><span class="line">                msg:&#39;hello&#39;,</span><br><span class="line">                books:[</span><br><span class="line">                    &#123;</span><br><span class="line">                        id: 1,</span><br><span class="line">                        name: &#39;java零基础实战&#39;,</span><br><span class="line">                        author: &#39;KingOne&#39;</span><br><span class="line">                    &#125;,</span><br><span class="line">                    &#123;</span><br><span class="line">                        id: 2,</span><br><span class="line">                        name: &#39;Spring零基础实战&#39;,</span><br><span class="line">                        author: &#39;KingOne2&#39;</span><br><span class="line">                    &#125;,</span><br><span class="line">                    &#123;</span><br><span class="line">                        id: 3,</span><br><span class="line">                        name: &#39;java零基础实战2&#39;,</span><br><span class="line">                        author: &#39;KingOne&#39;</span><br><span class="line">                    &#125;</span><br><span class="line">                ]</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        created()&#123;</span><br><span class="line">            &#x2F;*由于此处是在页面一经访问时出现，可以将数据写在此处*&#x2F;</span><br><span class="line">            alert(&quot;你好，欢迎访问&quot;);</span><br><span class="line"></span><br><span class="line">            &#x2F;*查询后端内容的语法*&#x2F;</span><br><span class="line">            const _this &#x3D; this;     &#x2F;&#x2F;此处是将vue中的this赋值给当前回调中的——this</span><br><span class="line">            axios.get(&#39;http:&#x2F;&#x2F;localhost:8181&#x2F;book&#x2F;findAll&#39;).then(function (resp) &#123;</span><br><span class="line">                _this.books &#x3D; resp.data;</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">    &#x2F;*可完成CSS的内容*&#x2F;</span><br><span class="line">&lt;&#x2F;style&gt;</span><br></pre></td></tr></table></figure>

<p>如果在访问前端的端口时，出现了信息回传错误，<strong>是因为“跨域访问”的问题。</strong>对此，可以考虑在后端中解决:</p>
<p>即在config文件中编写配置类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.CorsRegistry;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.servlet.config.annotation.WebMvcConfigurer;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CrosConfig</span> <span class="keyword">implements</span> <span class="title">WebMvcConfigurer</span></span>&#123;</span><br><span class="line">    <span class="comment">/*此处解决跨域访问问题*/</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addCorsMappings</span><span class="params">(CorsRegistry registry)</span> </span>&#123;</span><br><span class="line">        registry.addMapping(<span class="string">&quot;/**&quot;</span>)</span><br><span class="line">                .allowedOriginPatterns(<span class="string">&quot;*&quot;</span>)</span><br><span class="line">                .allowedMethods(<span class="string">&quot;GET&quot;</span>, <span class="string">&quot;HEAD&quot;</span>, <span class="string">&quot;POST&quot;</span>, <span class="string">&quot;PUT&quot;</span>, <span class="string">&quot;DELETE&quot;</span>, <span class="string">&quot;OPTIONS&quot;</span>)</span><br><span class="line">                .allowCredentials(<span class="keyword">true</span>)</span><br><span class="line">                .maxAge(<span class="number">3600</span>)</span><br><span class="line">                .allowedHeaders(<span class="string">&quot;*&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="三、Element-UI的使用："><a href="#三、Element-UI的使用：" class="headerlink" title="三、Element-UI的使用："></a>三、Element-UI的使用：</h1><h2 id="1、element-ui的安装："><a href="#1、element-ui的安装：" class="headerlink" title="1、element-ui的安装："></a>1、element-ui的安装：</h2><p>（1）先使用vue cli创建一个前端项目仪表盘；</p>
<p>（2）添加element-ui插件；</p>
<blockquote>
<p>通过“插件”选项，添加“vue-cli-plugin-element 1.0.1”插件即可；</p>
</blockquote>
<p>（3）设置：保持默认即可。</p>
<h2 id="2、操作及使用："><a href="#2、操作及使用：" class="headerlink" title="2、操作及使用："></a>2、操作及使用：</h2><p>（1）通过IDEA打开我们的前端项目，并了解element-ui的开发手册(<strong>快速上手文件</strong>等)；</p>
<blockquote>
<p>主要关注的几个标签：</p>
<ul>
<li><p>el-container:用于控制整个页面的结构与布局；</p>
</li>
<li><p>el-aside:用于构建左侧的菜单栏；</p>
</li>
<li><p>el-menu: 用于构建左侧的菜单栏内容，常用属性：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;el-menu :default-openeds&#x3D;&quot;[&#39;1&#39;, &#39;3&#39;]&quot; :default-active&#x3D;&quot;&#39;1-1&#39;&quot;&gt;</span><br></pre></td></tr></table></figure>

<blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;:<span class="keyword">default</span>-openeds  默认展开的菜单，且是通过菜单的index值进行确定。且可以置为空，表示全部关闭。</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;:<span class="keyword">default</span>-active  默认选中的菜单，且是通过菜单的index值进行确定。</span><br></pre></td></tr></table></figure>
</blockquote>
</li>
<li><p>el-submenu:  可展开的菜单，常用属性：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">index:  菜单的下标,文本类型，不能是数值类型。</span><br></pre></td></tr></table></figure>
</li>
<li><p>template:  对应el-submenu的菜单名。</p>
</li>
<li><p>i: 设置菜单图标，通过class属性实现。参考：<a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/icon">组件 | Element</a></p>
<blockquote>
<p>常用属性：</p>
<p>el-icon-menu ；  el-icon-message ； el-setting</p>
</blockquote>
</li>
<li><p>el-menu-item: 菜单的不可再展开的子节点，</p>
</li>
<li><p>常用属性：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">index:  菜单的下标,文本类型，不能是数值类型。</span><br></pre></td></tr></table></figure>
</li>
</ul>
</blockquote>
<h3 id="具体使用："><a href="#具体使用：" class="headerlink" title="具体使用："></a>具体使用：</h3><h4 id="注意事项："><a href="#注意事项：" class="headerlink" title="注意事项："></a><strong>注意事项：</strong></h4><blockquote>
<ul>
<li>router与route的不同：</li>
</ul>
<blockquote>
<p>router可以理解为路由器，包含多个路由信息，在路由跳转时使用；</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="keyword">this</span>.$router.push(&#123;</span><br><span class="line">                   path: <span class="string">&#x27;/updateBook&#x27;</span>,</span><br><span class="line">                   query: &#123;</span><br><span class="line">                       id: row.id</span><br><span class="line">                   &#125;</span><br><span class="line">               &#125;);</span><br></pre></td></tr></table></figure>

<p>route可以理解为某一路由信息，在获取某个路由信息时使用；</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="keyword">this</span>.$route.query.id</span><br></pre></td></tr></table></figure>
</blockquote>
<ul>
<li>后端中的@RequestBody  和 @PathVariable：</li>
</ul>
<blockquote>
<p>@RequestBody是为了注明请求对象，即<strong>路径访问中的对象</strong>；</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping(&quot;/save&quot;)</span>       <span class="comment">/*此处为提交请求。*/</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">save</span><span class="params">(<span class="meta">@RequestBody</span>  Book book)</span></span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<p>@PathVariable是为了<strong>注明访问参数</strong>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="meta">@GetMapping(&quot;/findById/&#123;id&#125;&quot;)</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> Book <span class="title">findById</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> Integer id)</span></span>&#123;</span><br><span class="line">       &#125;</span><br></pre></td></tr></table></figure>
</blockquote>
<ul>
<li>后端中的@PutMapping  @PostMapping和 @GetMapping:</li>
</ul>
<blockquote>
<p>@PutMapping:可用于<strong>内容更新</strong>时的提交；</p>
<p>@PostMapping：可用于<strong>添加</strong>时的提交；</p>
<p>@GetMapping：用于数据<strong>获取</strong>时的提交；</p>
<p>@DeleteMapping: 用于<strong>数据删除</strong>时的提交</p>
</blockquote>
</blockquote>
<h3 id="1-先在main-js中引入element-ui的使用；"><a href="#1-先在main-js中引入element-ui的使用；" class="headerlink" title="1.先在main.js中引入element-ui的使用；"></a>1.先在main.js中引入element-ui的使用；</h3><p>(<strong>可以不使用，避免出现页面刷新不出来的问题</strong>。)</p>
<blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="keyword">import</span> Vue from <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line">&gt;<span class="keyword">import</span> ElementUI from <span class="string">&#x27;element-ui&#x27;</span>;</span><br><span class="line">&gt;<span class="keyword">import</span> <span class="string">&#x27;element-ui/lib/theme-chalk/index.css&#x27;</span>;</span><br><span class="line">&gt;<span class="keyword">import</span> App from <span class="string">&#x27;./App.vue&#x27;</span>;</span><br><span class="line"></span><br><span class="line">&gt;Vue.use(ElementUI);</span><br><span class="line"></span><br><span class="line">&gt;<span class="keyword">new</span> Vue(&#123;</span><br><span class="line"> el: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line"> render: h =&gt; h(App)</span><br><span class="line">&gt;&#125;);</span><br></pre></td></tr></table></figure>
</blockquote>
<h3 id="2-了解网页布局部分："><a href="#2-了解网页布局部分：" class="headerlink" title="2.了解网页布局部分："></a>2.了解网页布局部分：</h3><p>对于后端页面，一般需要包括“header  main  aside”三大部分；</p>
<p>并选择一个符合要求的实例，并将代码截取过来，进行对应放置:</p>
<blockquote>
<p>如<el-container></el-container>部分的代码放置在<template><div></div></template>标签中；</p>
<p>并将<script></script>&gt;与<style></style>&gt;文件分别进行对应覆盖即可。</p>

<p>​       效果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id&#x3D;&quot;app&quot;&gt;</span><br><span class="line">    &lt;el-container style&#x3D;&quot;height: 500px; border: 1px solid #eee&quot;&gt;</span><br><span class="line">      &lt;el-aside width&#x3D;&quot;200px&quot; style&#x3D;&quot;background-color: rgb(238, 241, 246)&quot;&gt;</span><br><span class="line">        &lt;el-menu :default-openeds&#x3D;&quot;[&#39;1&#39;, &#39;3&#39;]&quot;&gt;</span><br><span class="line">          &lt;el-submenu index&#x3D;&quot;1&quot;&gt;</span><br><span class="line">            &lt;template slot&#x3D;&quot;title&quot;&gt;&lt;i class&#x3D;&quot;el-icon-message&quot;&gt;&lt;&#x2F;i&gt;导航一&lt;&#x2F;template&gt;</span><br><span class="line">            &lt;el-menu-item-group&gt;</span><br><span class="line">              &lt;template slot&#x3D;&quot;title&quot;&gt;分组一&lt;&#x2F;template&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;1-1&quot;&gt;选项1&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;1-2&quot;&gt;选项2&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-menu-item-group&gt;</span><br><span class="line">            &lt;el-menu-item-group title&#x3D;&quot;分组2&quot;&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;1-3&quot;&gt;选项3&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-menu-item-group&gt;</span><br><span class="line">            &lt;el-submenu index&#x3D;&quot;1-4&quot;&gt;</span><br><span class="line">              &lt;template slot&#x3D;&quot;title&quot;&gt;选项4&lt;&#x2F;template&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;1-4-1&quot;&gt;选项4-1&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-submenu&gt;</span><br><span class="line">          &lt;&#x2F;el-submenu&gt;</span><br><span class="line">          &lt;el-submenu index&#x3D;&quot;2&quot;&gt;</span><br><span class="line">            &lt;template slot&#x3D;&quot;title&quot;&gt;&lt;i class&#x3D;&quot;el-icon-menu&quot;&gt;&lt;&#x2F;i&gt;导航二&lt;&#x2F;template&gt;</span><br><span class="line">            &lt;el-menu-item-group&gt;</span><br><span class="line">              &lt;template slot&#x3D;&quot;title&quot;&gt;分组一&lt;&#x2F;template&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;2-1&quot;&gt;选项1&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;2-2&quot;&gt;选项2&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-menu-item-group&gt;</span><br><span class="line">            &lt;el-menu-item-group title&#x3D;&quot;分组2&quot;&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;2-3&quot;&gt;选项3&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-menu-item-group&gt;</span><br><span class="line">            &lt;el-submenu index&#x3D;&quot;2-4&quot;&gt;</span><br><span class="line">              &lt;template slot&#x3D;&quot;title&quot;&gt;选项4&lt;&#x2F;template&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;2-4-1&quot;&gt;选项4-1&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-submenu&gt;</span><br><span class="line">          &lt;&#x2F;el-submenu&gt;</span><br><span class="line">          &lt;el-submenu index&#x3D;&quot;3&quot;&gt;</span><br><span class="line">            &lt;template slot&#x3D;&quot;title&quot;&gt;&lt;i class&#x3D;&quot;el-icon-setting&quot;&gt;&lt;&#x2F;i&gt;导航三&lt;&#x2F;template&gt;</span><br><span class="line">            &lt;el-menu-item-group&gt;</span><br><span class="line">              &lt;template slot&#x3D;&quot;title&quot;&gt;分组一&lt;&#x2F;template&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;3-1&quot;&gt;选项1&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;3-2&quot;&gt;选项2&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-menu-item-group&gt;</span><br><span class="line">            &lt;el-menu-item-group title&#x3D;&quot;分组2&quot;&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;3-3&quot;&gt;选项3&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-menu-item-group&gt;</span><br><span class="line">            &lt;el-submenu index&#x3D;&quot;3-4&quot;&gt;</span><br><span class="line">              &lt;template slot&#x3D;&quot;title&quot;&gt;选项4&lt;&#x2F;template&gt;</span><br><span class="line">              &lt;el-menu-item index&#x3D;&quot;3-4-1&quot;&gt;选项4-1&lt;&#x2F;el-menu-item&gt;</span><br><span class="line">            &lt;&#x2F;el-submenu&gt;</span><br><span class="line">          &lt;&#x2F;el-submenu&gt;</span><br><span class="line">        &lt;&#x2F;el-menu&gt;</span><br><span class="line">      &lt;&#x2F;el-aside&gt;</span><br><span class="line"></span><br><span class="line">      &lt;el-container&gt;</span><br><span class="line">        &lt;el-header style&#x3D;&quot;text-align: right; font-size: 12px&quot;&gt;</span><br><span class="line">          &lt;el-dropdown&gt;</span><br><span class="line">            &lt;i class&#x3D;&quot;el-icon-setting&quot; style&#x3D;&quot;margin-right: 15px&quot;&gt;&lt;&#x2F;i&gt;</span><br><span class="line">            &lt;el-dropdown-menu slot&#x3D;&quot;dropdown&quot;&gt;</span><br><span class="line">              &lt;el-dropdown-item&gt;查看&lt;&#x2F;el-dropdown-item&gt;</span><br><span class="line">              &lt;el-dropdown-item&gt;新增&lt;&#x2F;el-dropdown-item&gt;</span><br><span class="line">              &lt;el-dropdown-item&gt;删除&lt;&#x2F;el-dropdown-item&gt;</span><br><span class="line">            &lt;&#x2F;el-dropdown-menu&gt;</span><br><span class="line">          &lt;&#x2F;el-dropdown&gt;</span><br><span class="line">          &lt;span&gt;王小虎&lt;&#x2F;span&gt;</span><br><span class="line">        &lt;&#x2F;el-header&gt;</span><br><span class="line"></span><br><span class="line">        &lt;el-main&gt;</span><br><span class="line">          &lt;el-table :data&#x3D;&quot;tableData&quot;&gt;</span><br><span class="line">            &lt;el-table-column prop&#x3D;&quot;date&quot; label&#x3D;&quot;日期&quot; width&#x3D;&quot;140&quot;&gt;</span><br><span class="line">            &lt;&#x2F;el-table-column&gt;</span><br><span class="line">            &lt;el-table-column prop&#x3D;&quot;name&quot; label&#x3D;&quot;姓名&quot; width&#x3D;&quot;120&quot;&gt;</span><br><span class="line">            &lt;&#x2F;el-table-column&gt;</span><br><span class="line">            &lt;el-table-column prop&#x3D;&quot;address&quot; label&#x3D;&quot;地址&quot;&gt;</span><br><span class="line">            &lt;&#x2F;el-table-column&gt;</span><br><span class="line">          &lt;&#x2F;el-table&gt;</span><br><span class="line">        &lt;&#x2F;el-main&gt;</span><br><span class="line">      &lt;&#x2F;el-container&gt;</span><br><span class="line">    &lt;&#x2F;el-container&gt;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;</span><br><span class="line">  .el-header &#123;</span><br><span class="line">    background-color: #B3C0D1;</span><br><span class="line">    color: #333;</span><br><span class="line">    line-height: 60px;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  .el-aside &#123;</span><br><span class="line">    color: #333;</span><br><span class="line">  &#125;</span><br><span class="line">&lt;&#x2F;style&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">    export default &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">            const item &#x3D; &#123;</span><br><span class="line">                date: &#39;2016-05-02&#39;,</span><br><span class="line">                name: &#39;王小虎&#39;,</span><br><span class="line">                address: &#39;上海市普陀区金沙江路 1518 弄&#39;</span><br><span class="line">            &#125;;</span><br><span class="line">            return &#123;</span><br><span class="line">                tableData: Array(20).fill(item)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure>

<h3 id="3-使用Vue-router动态构建左侧菜单栏"><a href="#3-使用Vue-router动态构建左侧菜单栏" class="headerlink" title="3.使用Vue router动态构建左侧菜单栏,"></a>3.使用<strong>Vue route</strong>r动态构建左侧菜单栏,</h3><p><strong>实现根据不通过路径展现不同的内容</strong>：</p>
<blockquote>
<ul>
<li>先根据需求，写好对应的页面Vue组件；并在router中引入和写好跳转路由；</li>
<li>在router的index.js中写跳转路径时，注意引入对应的vue组件，和编写对应的路径信息；</li>
<li>如果想把经router链接过去的内容展示出来，注意在App.vue中使用<router-view></router-view></li>
</ul>
</blockquote>
<p>(1)对于一个“一级路由下**有多个子路由(即通过Children属性包覆)**”，先获取每个一级路由时：</p>
<blockquote>
<p>在App.vue中，使用“<el-submenu v-for="(item,index) in $router.options.routes"></el-submenu>”实现获取与显示。</p>
<ul>
<li><p>注意上述的item表示各个元素；index表示对应的索引号；</p>
</li>
<li><p>且在未使用index属性的时候，会导致默认的各路由的下标索引相同，会产生同时折叠或展开的情况。因此需要设置index:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;el-submenu v-<span class="keyword">for</span>=<span class="string">&quot;(item,index) in $router.options.routes&quot;</span> :index=<span class="string">&quot;index+‘ ’&quot;</span>&gt;</span><br><span class="line">&lt;/el-submenu&gt;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</blockquote>
<p>(2)如果在页面显示时出现了嵌套的状况，是“App.vue主窗口出现了太多配置”的原因。因此考虑将App.vue进行拆分，只保留**<router-view></router-view>**,其他内容转移到index.vue即可：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">App.vue:   <span class="comment">//只保留router显示的主窗口</span></span><br><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id=<span class="string">&quot;app&quot;</span>&gt;</span><br><span class="line">    &lt;!--router路由内容展示页面--&gt;</span><br><span class="line">    &lt;router-view&gt; &lt;/router-view&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;!--此处是CSS样式文件--&gt;</span><br><span class="line">&lt;style&gt;</span><br><span class="line">  ...</span><br><span class="line">&lt;/style&gt;</span><br><span class="line"></span><br><span class="line">&lt;!--此处是JavaScript文件--&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">   ...</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line">Index.vue部分参考：<span class="comment">//实现将&lt;template&gt;部分内容的转移</span></span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;el-container style=<span class="string">&quot;height: 500px; border: 1px solid #eee&quot;</span>&gt;</span><br><span class="line">        &lt;el-aside width=<span class="string">&quot;200px&quot;</span> style=<span class="string">&quot;background-color: rgb(238, 241, 246)&quot;</span>&gt;   &lt;!--此处是边栏设置--&gt;</span><br><span class="line">            &lt;!--&lt;el-menu :<span class="keyword">default</span>-openeds=<span class="string">&quot;[&#x27;1&#x27;]&quot;</span> :<span class="keyword">default</span>-active=<span class="string">&quot;&#x27;1-1&#x27;&quot;</span>&gt;</span><br><span class="line">              &lt;el-submenu index=<span class="string">&quot;1&quot;</span>&gt;    &amp;lt;!&amp;ndash;此处为可展开页面设置&amp;ndash;&amp;gt;</span><br><span class="line">                &lt;template slot=&quot;title&quot;&gt;&lt;i class=&quot;el-icon-message&quot;&gt;&lt;/i&gt;导航一&lt;/template&gt;</span><br><span class="line">                &lt;el-menu-item-group&gt;    &amp;lt;!&amp;ndash;此处为导航一的组内部件&amp;ndash;&amp;gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;1-1&quot;&gt;选项1&lt;/el-menu-item&gt;    &amp;lt;!&amp;ndash;不可分菜单部件&amp;ndash;&amp;gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;1-2&quot;&gt;选项2&lt;/el-menu-item&gt;</span><br><span class="line"></span><br><span class="line">                  &lt;el-submenu index=<span class="string">&quot;1-3&quot;</span>&gt;</span><br><span class="line">                    &lt;template slot=&quot;title&quot;&gt;&lt;i class=&quot;el-icon-message&quot;&gt;&lt;/i&gt;选项3&lt;/template&gt;</span><br><span class="line">                    &lt;el-menu-item index=&quot;1-3-1&quot;&gt;选项3-1&lt;/el-menu-item&gt;</span><br><span class="line">                    &lt;el-menu-item index=&quot;1-3-2&quot;&gt;选项3-2&lt;/el-menu-item&gt;</span><br><span class="line">                  &lt;/el-submenu&gt;</span><br><span class="line">                &lt;/el-menu-item-group&gt;</span><br><span class="line">              &lt;/el-submenu&gt;</span><br><span class="line">              &amp;lt;!&amp;ndash;&lt;el-submenu index=<span class="string">&quot;2&quot;</span>&gt;</span><br><span class="line">                &lt;template slot=&quot;title&quot;&gt;&lt;i class=&quot;el-icon-menu&quot;&gt;&lt;/i&gt;导航二&lt;/template&gt;</span><br><span class="line">                &lt;el-menu-item-group&gt;</span><br><span class="line">                  &lt;template slot=&quot;title&quot;&gt;分组一&lt;/template&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;2-1&quot;&gt;选项1&lt;/el-menu-item&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;2-2&quot;&gt;选项2&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-menu-item-group&gt;</span><br><span class="line">                &lt;el-menu-item-group title=<span class="string">&quot;分组2&quot;</span>&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;2-3&quot;&gt;选项3&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-menu-item-group&gt;</span><br><span class="line">                &lt;el-submenu index=<span class="string">&quot;2-4&quot;</span>&gt;</span><br><span class="line">                  &lt;template slot=&quot;title&quot;&gt;选项4&lt;/template&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;2-4-1&quot;&gt;选项4-1&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-submenu&gt;</span><br><span class="line">              &lt;/el-submenu&gt;</span><br><span class="line"></span><br><span class="line">              &lt;el-submenu index=<span class="string">&quot;3&quot;</span>&gt;</span><br><span class="line">                &lt;template slot=&quot;title&quot;&gt;&lt;i class=&quot;el-icon-setting&quot;&gt;&lt;/i&gt;导航三&lt;/template&gt;</span><br><span class="line">                &lt;el-menu-item-group&gt;</span><br><span class="line">                  &lt;template slot=&quot;title&quot;&gt;分组一&lt;/template&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;3-1&quot;&gt;选项1&lt;/el-menu-item&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;3-2&quot;&gt;选项2&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-menu-item-group&gt;</span><br><span class="line">                &lt;el-menu-item-group title=<span class="string">&quot;分组2&quot;</span>&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;3-3&quot;&gt;选项3&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-menu-item-group&gt;</span><br><span class="line">                &lt;el-submenu index=<span class="string">&quot;3-4&quot;</span>&gt;</span><br><span class="line">                  &lt;template slot=&quot;title&quot;&gt;选项4&lt;/template&gt;</span><br><span class="line">                  &lt;el-menu-item index=&quot;3-4-1&quot;&gt;选项4-1&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-submenu&gt;</span><br><span class="line">              &lt;/el-submenu&gt;&amp;ndash;&amp;gt;</span><br><span class="line">            &lt;/el-menu&gt;--&gt;</span><br><span class="line"></span><br><span class="line">            &lt;el-menu&gt;   &lt;!--实现菜单栏--&gt;</span><br><span class="line">                &lt;!--此处实现从router中的routers对象的一级路由的取值与展示--&gt;</span><br><span class="line">                &lt;el-submenu v-<span class="keyword">for</span>=<span class="string">&quot;(item,index) in $router.options.routes&quot;</span> :index=<span class="string">&quot;index+&#x27;&#x27; &quot;</span>&gt;    &lt;!--用于实现可多层的可展开菜单栏--&gt;</span><br><span class="line">                    &lt;template slot=&quot;title&quot;&gt;&lt;i class=&quot;el-icon-message&quot;&gt;&lt;/i&gt;&#123;&#123;item.name&#125;&#125;&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">                    &lt;!--此处获取一级路由下的二级路由children的信息展示--&gt;</span><br><span class="line">                    &lt;el-menu-item v-for=&quot;(item2,index2) in item.children&quot; :index=&quot;index+&#x27;-&#x27;+index2&quot;&gt;&#123;&#123;item2.name&#125;&#125;&lt;/el-menu-item&gt;</span><br><span class="line">                &lt;/el-submenu&gt;</span><br><span class="line">            &lt;/el-menu&gt;</span><br><span class="line">        &lt;/el-aside&gt;</span><br><span class="line"></span><br><span class="line">        &lt;el-container&gt;</span><br><span class="line">            &lt;el-header style=<span class="string">&quot;text-align: right; font-size: 12px&quot;</span>&gt;  &lt;!--此处是网页的内容头部页面--&gt;</span><br><span class="line">                &lt;el-dropdown&gt;</span><br><span class="line">                    &lt;i class=&quot;el-icon-setting&quot; style=&quot;margin-right: 15px&quot;&gt;执行操作&lt;/i&gt;</span><br><span class="line">                    &lt;el-dropdown-menu slot=<span class="string">&quot;dropdown&quot;</span>&gt;</span><br><span class="line">                        &lt;el-dropdown-item&gt;查看&lt;/el-dropdown-item&gt;</span><br><span class="line">                        &lt;el-dropdown-item&gt;新增&lt;/el-dropdown-item&gt;</span><br><span class="line">                        &lt;el-dropdown-item&gt;删除&lt;/el-dropdown-item&gt;</span><br><span class="line">                    &lt;/el-dropdown-menu&gt;</span><br><span class="line">                &lt;/el-dropdown&gt;</span><br><span class="line">                &lt;span&gt;王小虎&lt;/span&gt;</span><br><span class="line">            &lt;/el-header&gt;</span><br><span class="line"></span><br><span class="line">            &lt;el-main&gt;     &lt;!--此处是网页的内容展示页面--&gt;</span><br><span class="line">                &lt;!--&lt;el-table :data=<span class="string">&quot;tableData&quot;</span>&gt;</span><br><span class="line">                  &lt;el-table-column prop=<span class="string">&quot;date&quot;</span> label=<span class="string">&quot;日期&quot;</span> width=<span class="string">&quot;140&quot;</span>&gt;</span><br><span class="line">                  &lt;/el-table-column&gt;</span><br><span class="line">                  &lt;el-table-column prop=<span class="string">&quot;name&quot;</span> label=<span class="string">&quot;姓名&quot;</span> width=<span class="string">&quot;120&quot;</span>&gt;</span><br><span class="line">                  &lt;/el-table-column&gt;</span><br><span class="line">                  &lt;el-table-column prop=<span class="string">&quot;address&quot;</span> label=<span class="string">&quot;地址&quot;</span>&gt;</span><br><span class="line">                  &lt;/el-table-column&gt;</span><br><span class="line">                &lt;/el-table&gt;--&gt;</span><br><span class="line">                &lt;!--如果想把router链接过来的内容正确显示，需要放在此处--&gt;</span><br><span class="line"></span><br><span class="line">                &lt;!--此处是经router路由跳转过来的信息展示--&gt;</span><br><span class="line">                &lt;router-view&gt;&lt;/router-view&gt;</span><br><span class="line">            &lt;/el-main&gt;</span><br><span class="line">        &lt;/el-container&gt;</span><br><span class="line">    &lt;/el-container&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">    export <span class="keyword">default</span> &#123;</span><br><span class="line">        name: <span class="string">&quot;index&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line"></span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure>

<h3 id="4-菜单Menu和router的绑定："><a href="#4-菜单Menu和router的绑定：" class="headerlink" title="4.菜单Menu和router的绑定："></a>4.菜单Menu和router的绑定：</h3><p><strong>实现<router-view>内容显示和菜单选项的结合</router-view></strong>。</p>
<blockquote>
<p>(1) 在<el-menu>标签添加router属性；用于表名此处可由router进行控制；</el-menu></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;&lt;el-menu router&gt; </span><br></pre></td></tr></table></figure>

<p>(2) 在页面中添加<router-view>标签，它是一个容器，可动态渲染指定router的内容；</router-view></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;&lt;router-view&gt;&lt;/router-view&gt;</span><br></pre></td></tr></table></figure>

<p>(3) <el-menu-item>(<strong>不可展开的子菜单</strong>)标签的index值就是要跳转的router。</el-menu-item></p>
<blockquote>
<p>注意：:index=”item2.path”的使用：将item2元素的路径信息作为index下标，实现菜单和内容的连接。</p>
</blockquote>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;&lt;el-menu-item v-for=&quot;(item2,index2) in item.children&quot; :index=&quot;item2.path&quot;&gt;&#123;&#123;item2.name&#125;&#125;&lt;/el-menu-item&gt;</span><br></pre></td></tr></table></figure>
</blockquote>
<blockquote>
<ul>
<li>1.对于redirect重定向的使用：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&gt;&#123;</span><br><span class="line">     path:<span class="string">&#x27;/&#x27;</span>,</span><br><span class="line">     name:<span class="string">&#x27;导航1&#x27;</span>,</span><br><span class="line">     component:Index,</span><br><span class="line">     redirect: <span class="string">&#x27;/pageOne&#x27;</span>,     <span class="comment">/*此处为重定向；即在访问path时，发生二次跳转到redirect路径*/</span>      </span><br><span class="line">&gt;&#125;</span><br></pre></td></tr></table></figure>

<p><strong>根据重定向信息，可以实现在访问path路径时，再次访问redirect中的路径信息，实现内容的加载。</strong></p>
<ul>
<li><p>2.当我们访问某个对应的router时，需要将对应的菜单标为高亮：</p>
<blockquote>
<p><strong>使用:class属性，并且在访问路径和菜单元素的路径相同时，标记为激活状态；</strong></p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;el-menu-item v-for&#x3D;&quot;(item2,index2) in item.children&quot; :index&#x3D;&quot;item2.path&quot; </span><br><span class="line">                      :class&#x3D;&quot;$route.path&#x3D;&#x3D;item2.path?&#39;is-active&#39;:&#39;&#39;&quot;&gt;&#123;&#123;item2.name&#125;&#125;&lt;&#x2F;el-menu-item&gt;</span><br></pre></td></tr></table></figure>
</li>
</ul>
</blockquote>
<h3 id="5-前后端分离的数据对接问题："><a href="#5-前后端分离的数据对接问题：" class="headerlink" title="5. 前后端分离的数据对接问题："></a>5. 前后端分离的数据对接问题：</h3><p>（1）<strong>找到合适的table样式</strong>，并放到对应的页面组件(PageOne.vue)中;</p>
<blockquote>
<p>参考：</p>
<p><a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/table">组件 | Element</a></p>
</blockquote>
<p>（2）<strong>建立分页操作</strong>，此步骤是为了防止数据过多时，显示页面过于复杂。</p>
<blockquote>
<p>参考：</p>
<p><a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/pagination">组件 | Element</a></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line">        &lt;!--<span class="number">1.</span>配置表格组件--&gt;</span><br><span class="line">        &lt;el-table</span><br><span class="line">                :data=<span class="string">&quot;tableData&quot;</span></span><br><span class="line">                border</span><br><span class="line">                style=<span class="string">&quot;width: 100%&quot;</span>&gt;</span><br><span class="line">        &lt;/el-table&gt;</span><br><span class="line"></span><br><span class="line">        &lt;!--<span class="number">2.</span>配置分页--&gt;</span><br><span class="line">        &lt;el-pagination</span><br><span class="line">                background</span><br><span class="line">                layout=<span class="string">&quot;prev, pager, next&quot;</span></span><br><span class="line">                page-size=<span class="string">&quot;6&quot;</span>   <span class="comment">//配置每页的显示数量，且默认为10</span></span><br><span class="line">                <span class="meta">@current</span>-change=<span class="string">&quot;page&quot;</span>&gt;  &lt;!--配置当前页的触发事件page--&gt;</span><br><span class="line">                :total=<span class="string">&quot;1000&quot;</span>&gt;</span><br><span class="line">        &lt;/el-pagination&gt;</span><br><span class="line">        </span><br><span class="line">        &lt;!--<span class="number">3.</span>在script中完善page触发方法--&gt;</span><br><span class="line">        methods: &#123;</span><br><span class="line">            handleClick(row) &#123;</span><br><span class="line">                console.log(row);</span><br><span class="line">            &#125;,</span><br><span class="line">            page(currentPage)&#123;</span><br><span class="line">                <span class="keyword">const</span> _this = <span class="keyword">this</span>;     <span class="comment">//将全局的作用域转到function()内部</span></span><br><span class="line">            	axios.get(<span class="string">&#x27;http://localhost:8181/book/findAllByPage/&#x27;</span>+currentPage+<span class="string">&#x27;/6&#x27;</span>).then(function(resp)&#123; </span><br><span class="line">                _this.tableData = resp.data.content;    <span class="comment">//获取全体内容</span></span><br><span class="line">                _this.total = resp.data.totalElements;  <span class="comment">//获取所有数据条数</span></span><br><span class="line">            &#125;)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>(3) vue前端能够获取到测试数据后，即可<strong>考虑后台的数据获取</strong>(含分页显示)：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@GetMapping(&quot;&#x2F;findAllByPage&#x2F;&#123;page&#125;&#x2F;&#123;size&#125;&quot;)</span><br><span class="line">    &#x2F;*完成分页查找操作。注意：此处的page是从0开始的，与我们的分页数相差1；</span><br><span class="line">    * 因此在我们获取到分页数时，需要进行减1操作。*&#x2F;</span><br><span class="line">    public Page&lt;Book&gt; findAllByPage(@PathVariable(&quot;page&quot;) Integer page,</span><br><span class="line">                                    @PathVariable(&quot;size&quot;) Integer size)&#123;</span><br><span class="line">        Pageable pageable &#x3D; PageRequest.of(page-1,size);</span><br><span class="line">        return bookRepository.findAll(pageable);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>（4）完善前后端的数据对接：</p>
<ul>
<li><p>首先安装axios组件；</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue add axios</span><br></pre></td></tr></table></figure>
</li>
<li><p>完善获取方法：在<script>中<strong>完善数据获取created()方法</strong>：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*1.此处为从后台获取到的数据*/</span></span><br><span class="line">        created()&#123;</span><br><span class="line">            <span class="keyword">const</span> _this = <span class="keyword">this</span>;     <span class="comment">//将全局的作用域转到function()内部</span></span><br><span class="line">            axios.get(<span class="string">&#x27;http://localhost:8181/book/findAllByPage/1/6&#x27;</span>).then(function(resp)&#123;</span><br><span class="line">                <span class="comment">/*即将resp参数的data中的content内容赋值给tabledata属性参数*/</span></span><br><span class="line">                _this.tableData = resp.data.content;    <span class="comment">//获取全体内容</span></span><br><span class="line">                _this.total = resp.data.totalElements;  <span class="comment">//获取所有数据条数</span></span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>并和分页获取的事件**page(currentPage)**绑定：</p>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">page(currentPage)&#123;</span><br><span class="line">                const _this &#x3D; this;     &#x2F;&#x2F;将全局的作用域转到function()内部</span><br><span class="line">            	axios.get(&#39;http:&#x2F;&#x2F;localhost:8181&#x2F;book&#x2F;findAllByPage&#x2F;&#39;+currentPage+&#39;&#x2F;6&#39;).then(function(resp)&#123; </span><br><span class="line">                _this.tableData &#x3D; resp.data.content;    &#x2F;&#x2F;获取全体内容</span><br><span class="line">                _this.total &#x3D; resp.data.totalElements;  &#x2F;&#x2F;获取所有数据条数</span><br><span class="line">            &#125;)</span><br><span class="line">            &#125;</span><br></pre></td></tr></table></figure>

<h3 id="6-实现数据添加："><a href="#6-实现数据添加：" class="headerlink" title="6.实现数据添加："></a>6.实现数据添加：</h3><blockquote>
<ul>
<li><p>数据的增删需要<strong>通过表单进行实现</strong>；</p>
</li>
<li><p>页面跳转的实现：</p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="comment">/*完成信息添加成功后的，页面跳转*/</span></span><br><span class="line"> _this.$router.push(<span class="string">&#x27;/bookManage&#x27;</span>);</span><br></pre></td></tr></table></figure>
</blockquote>
<p>（1）先寻求一个合适的表单模板放到自己的操作页面中，<a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/form">组件 | Element</a></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;!--注意:model用于绑定数据对象  :rules为校验规则  ref可以理解为要参加校验的对象--&gt;</span><br><span class="line">    &lt;el-form :model=<span class="string">&quot;ruleForm&quot;</span> :rules=<span class="string">&quot;rules&quot;</span> ref=<span class="string">&quot;ruleForm&quot;</span> label-width=<span class="string">&quot;100px&quot;</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">&quot;demo-ruleForm&quot;</span>&gt;</span><br><span class="line">        </span><br><span class="line">        &lt;!--此处的label为标签名，prop为对应属性的校验规则--&gt;</span><br><span class="line">        &lt;el-form-item label=<span class="string">&quot;图书名称&quot;</span> prop=<span class="string">&quot;name&quot;</span>&gt;</span><br><span class="line">            &lt;!--v-model是获取数据对象的属性名称--&gt;</span><br><span class="line">            &lt;el-input v-model=&quot;ruleForm.name&quot;&gt;&lt;/el-input&gt;</span><br><span class="line">        &lt;/el-form-item&gt;</span><br><span class="line">         &lt;!--此处为按钮点击事件--&gt;</span><br><span class="line">        &lt;el-form-item&gt;</span><br><span class="line">            &lt;el-button type=&quot;primary&quot; @click=&quot;submitForm(&#x27;ruleForm&#x27;)&quot;&gt;立即创建&lt;/el-button&gt;</span><br><span class="line">            &lt;el-button @click=&quot;resetForm(&#x27;ruleForm&#x27;)&quot;&gt;重置&lt;/el-button&gt;</span><br><span class="line">        &lt;/el-form-item&gt;</span><br><span class="line">    &lt;/el-form&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">        export <span class="keyword">default</span> &#123;</span><br><span class="line">            data() &#123;</span><br><span class="line">                <span class="keyword">return</span> &#123;</span><br><span class="line">                    ruleForm: &#123;</span><br><span class="line">                        name: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">                        author: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">                    &#125;,</span><br><span class="line">                    rules: &#123;</span><br><span class="line">                        name: [</span><br><span class="line">                            &#123; required: <span class="keyword">true</span>, message: <span class="string">&#x27;请输入活动名称&#x27;</span>, trigger: <span class="string">&#x27;blur&#x27;</span> &#125;,</span><br><span class="line">                            &#123; min: <span class="number">3</span>, max: <span class="number">5</span>, message: <span class="string">&#x27;长度在 3 到 5 个字符&#x27;</span>, trigger: <span class="string">&#x27;blur&#x27;</span> &#125;</span><br><span class="line">                        ],</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;;</span><br><span class="line">            &#125;,</span><br><span class="line">            methods: &#123;</span><br><span class="line">                resetForm(formName) &#123;</span><br><span class="line">                    <span class="keyword">this</span>.$refs[formName].resetFields();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>（2）数据校验的流程：通过设置rules进行规则设定。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">rules: &#123;</span><br><span class="line">                        name: [</span><br><span class="line">                            <span class="comment">/*required设置是否为必须项；message为提示信息；trigger为触发事件的时刻*/</span></span><br><span class="line">                            &#123; required: <span class="keyword">true</span>, message: <span class="string">&#x27;请输入活动名称&#x27;</span>, trigger: <span class="string">&#x27;blur&#x27;</span> &#125;,</span><br><span class="line">                            &#123; min: <span class="number">3</span>, max: <span class="number">5</span>, message: <span class="string">&#x27;长度在 3 到 5 个字符&#x27;</span>, trigger: <span class="string">&#x27;blur&#x27;</span> &#125;</span><br><span class="line">                        ],</span><br><span class="line">                        author: [</span><br><span class="line">                            &#123; required: <span class="keyword">true</span>, message: <span class="string">&#x27;请输入作者名&#x27;</span>, trigger: <span class="string">&#x27;change&#x27;</span> &#125;</span><br><span class="line">                        ],</span><br><span class="line">                    &#125;</span><br></pre></td></tr></table></figure>

<p>（3）在后端获取数据：</p>
<ul>
<li><p>写Controller处理请求信息：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span> <span class="comment">//使用restful风格的controller注解，可以省去@ReposeBody注解</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/book&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BookHandler</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> BookRepository bookRepository;   <span class="comment">//其中含有数据操作对象</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@PostMapping(&quot;/save&quot;)</span>       <span class="comment">/*此处为提交请求。*/</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">save</span><span class="params">(<span class="meta">@RequestBody</span>  Book book)</span></span>&#123;</span><br><span class="line">        Book result = bookRepository.save(book);</span><br><span class="line">        <span class="keyword">if</span>(result !=<span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;success&quot;</span>;	<span class="comment">//向前端返回的data数据</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;error&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>对于entity对象，<strong>注意主键自增设置</strong>。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&gt;@Entity     &#x2F;&#x2F;使用此注解通过类名“book”和数据库中的“book”对应绑定</span><br><span class="line">&gt;@Data   &#x2F;&#x2F;自动生成getter setter</span><br><span class="line">&gt;public class Book &#123;</span><br><span class="line">  @Id</span><br><span class="line">  @GeneratedValue(strategy &#x3D; GenerationType.IDENTITY)     &#x2F;*注意IDENTITY表示主键由数据库自动生成*&#x2F;</span><br><span class="line">  private Integer id;</span><br><span class="line">  private String name;</span><br><span class="line">  private String author;</span><br><span class="line">  private String publish;</span><br><span class="line">&gt;&#125;</span><br></pre></td></tr></table></figure>
</blockquote>
</li>
</ul>
<p>（4）前端获取到数据后，并进行显示：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;*处理接收到后端对应网址的数据,并实现消息弹窗+页面成功跳转功能。*&#x2F;</span><br><span class="line">  axios.post(&#39;http:&#x2F;&#x2F;localhost:8181&#x2F;book&#x2F;save&#39;,this.ruleForm).then(function (resp) &#123;</span><br><span class="line">                               if(resp.data &#x3D;&#x3D; &quot;success&quot;)&#123;</span><br><span class="line">                                   &#x2F;*消息提示框设置：完成信息添加成功的提示后，再跳转*&#x2F;</span><br><span class="line">                                   _this.$alert(&#39;《&#39;+_this.ruleForm.name+&#39;》添加成功！&#39;, &#39;消息&#39;, &#123;</span><br><span class="line">                                       confirmButtonText: &#39;确定&#39;,</span><br><span class="line">                                       callback: action &#x3D;&gt; &#123;</span><br><span class="line">                                           &#x2F;*完成信息添加成功后的，页面跳转*&#x2F;</span><br><span class="line">                                           _this.$router.push(&#39;&#x2F;bookManage&#39;);</span><br><span class="line">                                       &#125;</span><br><span class="line">                                   &#125;);</span><br><span class="line">                               &#125;</span><br><span class="line">                           &#125;)</span><br></pre></td></tr></table></figure>

<h3 id="7-实现数据删除功能："><a href="#7-实现数据删除功能：" class="headerlink" title="7.实现数据删除功能："></a>7.实现数据删除功能：</h3><blockquote>
<p>实现思路：</p>
<p>（1）根据修改按钮，做好修改或删除的事件绑定，</p>
<p>（2）并设置修改页面的访问路由信息，并携带该项信息的id;</p>
<p>（3）将id信息传至端，获取对应的数据，并回传至修改页面进行显示；</p>
</blockquote>
<p>（1）修改按钮的事件绑定 &amp; 单击时的路径跳转：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;el-table&gt;</span><br><span class="line">	&lt;el-table-column</span><br><span class="line">                    fixed&#x3D;&quot;right&quot;</span><br><span class="line">                    label&#x3D;&quot;操作&quot;</span><br><span class="line">                    width&#x3D;&quot;150&quot;&gt;</span><br><span class="line">                &lt;template slot-scope&#x3D;&quot;scope&quot;&gt;</span><br><span class="line">                    &lt;el-button @click&#x3D;&quot;edit(scope.row)&quot; type&#x3D;&quot;text&quot; size&#x3D;&quot;small&quot;&gt;修改&lt;&#x2F;el-button&gt;</span><br><span class="line">                &lt;&#x2F;template&gt;</span><br><span class="line">    &lt;&#x2F;el-table-column&gt;</span><br><span class="line">&lt;&#x2F;el-table&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;中的事件详情</span><br><span class="line">edit(row) &#123;     &#x2F;&#x2F;row中封装了该行的信息内容</span><br><span class="line">                &#x2F;*实现思路：先获取到要修改内容的id；将id传至后台，将查询到的数据传给前端的修改页面；</span><br><span class="line">                * 修改页面结束后，将数据*&#x2F;</span><br><span class="line"></span><br><span class="line">                &#x2F;&#x2F;1.携带id信息的页面跳转</span><br><span class="line">                this.$router.push(&#123;</span><br><span class="line">                    path: &#39;&#x2F;updateBook&#39;,</span><br><span class="line">                    query: &#123;</span><br><span class="line">                        id: row.id</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">            &#125;,</span><br></pre></td></tr></table></figure>

<p>（2）后端数据的获取：</p>
<p>测试findById()方法可用以后，编写对应的Controller,并进行启动测试：</p>
<blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="meta">@Test</span></span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">findById</span><span class="params">()</span></span>&#123;</span><br><span class="line">       Book book = bookRepository.findById(<span class="number">1</span>).get();	<span class="comment">//注意get()的使用</span></span><br><span class="line">       System.out.println(book);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="meta">@GetMapping(&quot;/findById/&#123;id&#125;&quot;)</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> Book <span class="title">findById</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> Integer id)</span></span>&#123;</span><br><span class="line">       <span class="keyword">return</span> bookRepository.findById(id).get();   <span class="comment">//注意get()的使用</span></span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&gt;测试端口：  http:&#x2F;&#x2F;localhost:8181&#x2F;book&#x2F;findById&#x2F;2</span><br><span class="line">&gt;&#123;</span><br><span class="line">&gt;&quot;id&quot;: 2,</span><br><span class="line">&gt;&quot;name&quot;: &quot;追风筝的人&quot;,</span><br><span class="line">&gt;&quot;author&quot;: &quot;卡勒德·胡赛尼&quot;,</span><br><span class="line">&gt;&quot;publish&quot;: &quot;上海人民出版社&quot;</span><br><span class="line">&gt;&#125;</span><br></pre></td></tr></table></figure>
</blockquote>
<p>（3）在前端中拿到后端传回的数据，并显示：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">created()&#123;</span><br><span class="line">            <span class="comment">//此处实现功能：将id传至后台，获取数据后，重新拿到此处进行回显。</span></span><br><span class="line">            <span class="keyword">const</span> _this = <span class="keyword">this</span>;</span><br><span class="line">            axios.get(<span class="string">&#x27;http://localhost:8181/book/findById/&#x27;</span>+<span class="keyword">this</span>.$route.query.id).then(function (resp) &#123;</span><br><span class="line">                <span class="comment">//数据显示的完成：将对应的数据赋给此处的属性</span></span><br><span class="line">                _this.ruleForm = resp.data</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br></pre></td></tr></table></figure>

<p>(4)在修改页面完成操作后，点击“修改按钮”，重新传给后端，完成更新：</p>
<blockquote>
<p>后端中重复类似（2）中的操作,完成数据库的操作部分：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="meta">@Test</span></span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">update</span><span class="params">()</span></span>&#123;</span><br><span class="line">       <span class="comment">/*注意此处的save()方法时通过id进行对应的设置，如果未设置，则内容为空。*/</span></span><br><span class="line">       Book book = <span class="keyword">new</span> Book();</span><br><span class="line">       book.setId(<span class="number">23</span>);</span><br><span class="line">       book.setName(<span class="string">&quot;SPRT&quot;</span>);</span><br><span class="line">       bookRepository.save(book);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&gt;<span class="meta">@PutMapping(&quot;/update&quot;)</span>	<span class="comment">//注意@PutMapping的使用</span></span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">update</span><span class="params">(<span class="meta">@RequestBody</span> Book book)</span></span>&#123;</span><br><span class="line">       Book result = bookRepository.save(book);</span><br><span class="line">       <span class="keyword">if</span>(result !=<span class="keyword">null</span>)&#123;</span><br><span class="line">           <span class="keyword">return</span> <span class="string">&quot;success&quot;</span>;</span><br><span class="line">       &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">           <span class="keyword">return</span> <span class="string">&quot;error&quot;</span>;</span><br><span class="line">       &#125;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<p>完善“修改”按钮的功能：访问后端的对应修改程序url完成修改，进行消息提示，页面跳转功能：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&gt;methods: &#123;</span><br><span class="line">           &#x2F;*此处的submitForm事件的作用是：在校验审核通过且比较后端的数据相同时，弹出信息添加成功的提示*&#x2F;</span><br><span class="line">           submitForm(formName) &#123;</span><br><span class="line">               const _this &#x3D; this;</span><br><span class="line">               &#x2F;*此处为submitForm的事件*&#x2F;</span><br><span class="line">               this.$refs[formName].validate((valid) &#x3D;&gt; &#123;</span><br><span class="line">                   if (valid) &#123;    &#x2F;*即全部规则成立时，提示此消息。*&#x2F;</span><br><span class="line">                       &#x2F;*处理接收到后端对应网址的数据   this.ruleForm为对应的对象信息*&#x2F;</span><br><span class="line">              axios.put(&#39;http:&#x2F;&#x2F;localhost:8181&#x2F;book&#x2F;update&#39;,this.ruleForm).then(function (resp) &#123;</span><br><span class="line">                           if(resp.data &#x3D;&#x3D; &quot;success&quot;)&#123;</span><br><span class="line">                               &#x2F;*消息提示框设置：完成信息添加成功的提示后，再跳转*&#x2F;</span><br><span class="line">                               _this.$alert(&#39;《&#39;+_this.ruleForm.name+&#39;》修改成功！&#39;, &#39;消息&#39;, &#123;</span><br><span class="line">                                   confirmButtonText: &#39;确定&#39;,</span><br><span class="line">                                   callback: action &#x3D;&gt; &#123;</span><br><span class="line">                                       &#x2F;*完成信息添加成功后的，页面跳转*&#x2F;</span><br><span class="line">                                       _this.$router.push(&#39;&#x2F;bookManage&#39;);</span><br><span class="line">                                   &#125;</span><br><span class="line">                               &#125;);</span><br><span class="line">                           &#125;</span><br><span class="line">                       &#125;)</span><br><span class="line">                   &#125; else &#123;</span><br><span class="line">                       return false;</span><br><span class="line">                   &#125;</span><br><span class="line">               &#125;);</span><br><span class="line">           &#125;,</span><br></pre></td></tr></table></figure>
</blockquote>
<p>(5) 对于删除操作，与（4）大致相同：</p>
<blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&gt;@DeleteMapping(&quot;&#x2F;deleteById&#x2F;&#123;id&#125;&quot;)</span><br><span class="line">   public void deleteById(@PathVariable(&quot;id&quot;)Integer id)&#123;</span><br><span class="line">       bookRepository.deleteById(id);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&gt;deleteBook(row)&#123;</span><br><span class="line">               <span class="comment">//此处完成向后端发送id,让后端执行对应操作后，在进行跳转即可</span></span><br><span class="line">               <span class="keyword">const</span> _this = <span class="keyword">this</span>;</span><br><span class="line">               axios.delete(<span class="string">&#x27;http://localhost:8181/book/deleteById/&#x27;</span>+row.id).then(function (resp) &#123;</span><br><span class="line">                   <span class="comment">/*消息提示框设置：完成信息删除成功的提示后，再跳转*/</span></span><br><span class="line">                   _this.$alert(<span class="string">&#x27;《&#x27;</span>+row.name+<span class="string">&#x27;》删除成功！&#x27;</span>, <span class="string">&#x27;消息&#x27;</span>, &#123;</span><br><span class="line">                       confirmButtonText: <span class="string">&#x27;确定&#x27;</span>,</span><br><span class="line">                       callback: action =&gt; &#123;</span><br><span class="line">                           <span class="comment">//删除完成后，本地刷新</span></span><br><span class="line">                           window.location.reload();</span><br><span class="line">                       &#125;</span><br><span class="line">                   &#125;);</span><br><span class="line">               &#125;)</span><br><span class="line">           &#125;,</span><br></pre></td></tr></table></figure></blockquote>
</script></p></li></ul>
      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/04/11/Vue%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
    <article id="post-多线程学习" class="article article-type-post  article-index" itemscope itemprop="blogPost">
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2021/03/20/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%AD%A6%E4%B9%A0/">多线程学习</a>
    </h1>
  

        
        <a href="/2021/03/20/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%AD%A6%E4%B9%A0/" class="archive-article-date">
  	<time datetime="2021-03-20T09:43:35.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2021-03-20</time>
</a>
        
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="1-主线程调用-run-方法和调用-start-方法开启子线程的区别："><a href="#1-主线程调用-run-方法和调用-start-方法开启子线程的区别：" class="headerlink" title="1. 主线程调用 run 方法和调用 start 方法开启子线程的区别："></a>1. 主线程调用 run 方法和调用 start 方法开启子线程的区别：</h2><img src="/2021/03/20/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%AD%A6%E4%B9%A0/run()&start()%E5%8C%BA%E5%88%AB.png" class>
      

      
    </div>
    <div class="article-info article-info-index">
      
      
      

      
        <p class="article-more-link">
          <a class="article-more-a" href="/2021/03/20/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%AD%A6%E4%B9%A0/">展开全文 >></a>
        </p>
      

      
      <div class="clearfix"></div>
    </div>
  </div>
</article>

<aside class="wrap-side-operation">
    <div class="mod-side-operation">
        
        <div class="jump-container" id="js-jump-container" style="display:none;">
            <a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
                <i class="icon-font icon-back"></i>
            </a>
            <div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
                <i class="icon-font icon-plane jump-plane"></i>
            </div>
        </div>
        
        
    </div>
</aside>




  
  
    <nav id="page-nav">
      <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="extend next" rel="next" href="/page/2/">Next &amp;raquo;</a>
    </nav>
  


          </div>
        </div>
      </div>
      <footer id="footer">
  <div class="outer">
    <div id="footer-info">
      <div class="footer-left">
        &copy; 2021 忒休斯的Code
      </div>
      <div class="footer-right">
         
	  </div>
    </div>
    <div calss="count-span">
      <span id="busuanzi_container_site_pv">
          总访问量: <span id="busuanzi_value_site_pv"></span>
    </div>
  </div>
</footer>


<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    </div>
    <script>
	var yiliaConfig = {
		mathjax: false,
		isHome: true,
		isPost: false,
		isArchive: false,
		isTag: false,
		isCategory: false,
		open_in_new: false,
		toc_hide_index: true,
		root: "/",
		innerArchive: true,
		showTags: false
	}
</script>

<script>!function(t){function n(e){if(r[e])return r[e].exports;var i=r[e]={exports:{},id:e,loaded:!1};return t[e].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}var r={};n.m=t,n.c=r,n.p="./",n(0)}([function(t,n,r){r(195),t.exports=r(191)},function(t,n,r){var e=r(3),i=r(52),o=r(27),u=r(28),c=r(53),f="prototype",a=function(t,n,r){var s,l,h,v,p=t&a.F,d=t&a.G,y=t&a.S,g=t&a.P,b=t&a.B,m=d?e:y?e[n]||(e[n]={}):(e[n]||{})[f],x=d?i:i[n]||(i[n]={}),w=x[f]||(x[f]={});d&&(r=n);for(s in r)l=!p&&m&&void 0!==m[s],h=(l?m:r)[s],v=b&&l?c(h,e):g&&"function"==typeof h?c(Function.call,h):h,m&&u(m,s,h,t&a.U),x[s]!=h&&o(x,s,v),g&&w[s]!=h&&(w[s]=h)};e.core=i,a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,t.exports=a},function(t,n,r){var e=r(6);t.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},function(t,n){var r=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=r)},function(t,n){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,n){var r=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=r)},function(t,n){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,n,r){var e=r(126)("wks"),i=r(76),o=r(3).Symbol,u="function"==typeof o;(t.exports=function(t){return e[t]||(e[t]=u&&o[t]||(u?o:i)("Symbol."+t))}).store=e},function(t,n){var r={}.hasOwnProperty;t.exports=function(t,n){return r.call(t,n)}},function(t,n,r){var e=r(94),i=r(33);t.exports=function(t){return e(i(t))}},function(t,n,r){t.exports=!r(4)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,n,r){var e=r(2),i=r(167),o=r(50),u=Object.defineProperty;n.f=r(10)?Object.defineProperty:function(t,n,r){if(e(t),n=o(n,!0),e(r),i)try{return u(t,n,r)}catch(t){}if("get"in r||"set"in r)throw TypeError("Accessors not supported!");return"value"in r&&(t[n]=r.value),t}},function(t,n,r){t.exports=!r(18)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,n,r){var e=r(14),i=r(22);t.exports=r(12)?function(t,n,r){return e.f(t,n,i(1,r))}:function(t,n,r){return t[n]=r,t}},function(t,n,r){var e=r(20),i=r(58),o=r(42),u=Object.defineProperty;n.f=r(12)?Object.defineProperty:function(t,n,r){if(e(t),n=o(n,!0),e(r),i)try{return u(t,n,r)}catch(t){}if("get"in r||"set"in r)throw TypeError("Accessors not supported!");return"value"in r&&(t[n]=r.value),t}},function(t,n,r){var e=r(40)("wks"),i=r(23),o=r(5).Symbol,u="function"==typeof o;(t.exports=function(t){return e[t]||(e[t]=u&&o[t]||(u?o:i)("Symbol."+t))}).store=e},function(t,n,r){var e=r(67),i=Math.min;t.exports=function(t){return t>0?i(e(t),9007199254740991):0}},function(t,n,r){var e=r(46);t.exports=function(t){return Object(e(t))}},function(t,n){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,n,r){var e=r(63),i=r(34);t.exports=Object.keys||function(t){return e(t,i)}},function(t,n,r){var e=r(21);t.exports=function(t){if(!e(t))throw TypeError(t+" is not an object!");return t}},function(t,n){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,n){t.exports=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}}},function(t,n){var r=0,e=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++r+e).toString(36))}},function(t,n){var r={}.hasOwnProperty;t.exports=function(t,n){return r.call(t,n)}},function(t,n){var r=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=r)},function(t,n){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,n,r){var e=r(11),i=r(66);t.exports=r(10)?function(t,n,r){return e.f(t,n,i(1,r))}:function(t,n,r){return t[n]=r,t}},function(t,n,r){var e=r(3),i=r(27),o=r(24),u=r(76)("src"),c="toString",f=Function[c],a=(""+f).split(c);r(52).inspectSource=function(t){return f.call(t)},(t.exports=function(t,n,r,c){var f="function"==typeof r;f&&(o(r,"name")||i(r,"name",n)),t[n]!==r&&(f&&(o(r,u)||i(r,u,t[n]?""+t[n]:a.join(String(n)))),t===e?t[n]=r:c?t[n]?t[n]=r:i(t,n,r):(delete t[n],i(t,n,r)))})(Function.prototype,c,function(){return"function"==typeof this&&this[u]||f.call(this)})},function(t,n,r){var e=r(1),i=r(4),o=r(46),u=function(t,n,r,e){var i=String(o(t)),u="<"+n;return""!==r&&(u+=" "+r+'="'+String(e).replace(/"/g,"&quot;")+'"'),u+">"+i+"</"+n+">"};t.exports=function(t,n){var r={};r[t]=n(u),e(e.P+e.F*i(function(){var n=""[t]('"');return n!==n.toLowerCase()||n.split('"').length>3}),"String",r)}},function(t,n,r){var e=r(115),i=r(46);t.exports=function(t){return e(i(t))}},function(t,n,r){var e=r(116),i=r(66),o=r(30),u=r(50),c=r(24),f=r(167),a=Object.getOwnPropertyDescriptor;n.f=r(10)?a:function(t,n){if(t=o(t),n=u(n,!0),f)try{return a(t,n)}catch(t){}if(c(t,n))return i(!e.f.call(t,n),t[n])}},function(t,n,r){var e=r(24),i=r(17),o=r(145)("IE_PROTO"),u=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=i(t),e(t,o)?t[o]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?u:null}},function(t,n){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on  "+t);return t}},function(t,n){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,n){t.exports={}},function(t,n){t.exports=!0},function(t,n){n.f={}.propertyIsEnumerable},function(t,n,r){var e=r(14).f,i=r(8),o=r(15)("toStringTag");t.exports=function(t,n,r){t&&!i(t=r?t:t.prototype,o)&&e(t,o,{configurable:!0,value:n})}},function(t,n,r){var e=r(40)("keys"),i=r(23);t.exports=function(t){return e[t]||(e[t]=i(t))}},function(t,n,r){var e=r(5),i="__core-js_shared__",o=e[i]||(e[i]={});t.exports=function(t){return o[t]||(o[t]={})}},function(t,n){var r=Math.ceil,e=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?e:r)(t)}},function(t,n,r){var e=r(21);t.exports=function(t,n){if(!e(t))return t;var r,i;if(n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;if("function"==typeof(r=t.valueOf)&&!e(i=r.call(t)))return i;if(!n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,n,r){var e=r(5),i=r(25),o=r(36),u=r(44),c=r(14).f;t.exports=function(t){var n=i.Symbol||(i.Symbol=o?{}:e.Symbol||{});"_"==t.charAt(0)||t in n||c(n,t,{value:u.f(t)})}},function(t,n,r){n.f=r(15)},function(t,n){var r={}.toString;t.exports=function(t){return r.call(t).slice(8,-1)}},function(t,n){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on  "+t);return t}},function(t,n,r){var e=r(4);t.exports=function(t,n){return!!t&&e(function(){n?t.call(null,function(){},1):t.call(null)})}},function(t,n,r){var e=r(53),i=r(115),o=r(17),u=r(16),c=r(203);t.exports=function(t,n){var r=1==t,f=2==t,a=3==t,s=4==t,l=6==t,h=5==t||l,v=n||c;return function(n,c,p){for(var d,y,g=o(n),b=i(g),m=e(c,p,3),x=u(b.length),w=0,S=r?v(n,x):f?v(n,0):void 0;x>w;w++)if((h||w in b)&&(d=b[w],y=m(d,w,g),t))if(r)S[w]=y;else if(y)switch(t){case 3:return!0;case 5:return d;case 6:return w;case 2:S.push(d)}else if(s)return!1;return l?-1:a||s?s:S}}},function(t,n,r){var e=r(1),i=r(52),o=r(4);t.exports=function(t,n){var r=(i.Object||{})[t]||Object[t],u={};u[t]=n(r),e(e.S+e.F*o(function(){r(1)}),"Object",u)}},function(t,n,r){var e=r(6);t.exports=function(t,n){if(!e(t))return t;var r,i;if(n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;if("function"==typeof(r=t.valueOf)&&!e(i=r.call(t)))return i;if(!n&&"function"==typeof(r=t.toString)&&!e(i=r.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,n,r){var e=r(5),i=r(25),o=r(91),u=r(13),c="prototype",f=function(t,n,r){var a,s,l,h=t&f.F,v=t&f.G,p=t&f.S,d=t&f.P,y=t&f.B,g=t&f.W,b=v?i:i[n]||(i[n]={}),m=b[c],x=v?e:p?e[n]:(e[n]||{})[c];v&&(r=n);for(a in r)(s=!h&&x&&void 0!==x[a])&&a in b||(l=s?x[a]:r[a],b[a]=v&&"function"!=typeof x[a]?r[a]:y&&s?o(l,e):g&&x[a]==l?function(t){var n=function(n,r,e){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(n);case 2:return new t(n,r)}return new t(n,r,e)}return t.apply(this,arguments)};return n[c]=t[c],n}(l):d&&"function"==typeof l?o(Function.call,l):l,d&&((b.virtual||(b.virtual={}))[a]=l,t&f.R&&m&&!m[a]&&u(m,a,l)))};f.F=1,f.G=2,f.S=4,f.P=8,f.B=16,f.W=32,f.U=64,f.R=128,t.exports=f},function(t,n){var r=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=r)},function(t,n,r){var e=r(26);t.exports=function(t,n,r){if(e(t),void 0===n)return t;switch(r){case 1:return function(r){return t.call(n,r)};case 2:return function(r,e){return t.call(n,r,e)};case 3:return function(r,e,i){return t.call(n,r,e,i)}}return function(){return t.apply(n,arguments)}}},function(t,n,r){var e=r(183),i=r(1),o=r(126)("metadata"),u=o.store||(o.store=new(r(186))),c=function(t,n,r){var i=u.get(t);if(!i){if(!r)return;u.set(t,i=new e)}var o=i.get(n);if(!o){if(!r)return;i.set(n,o=new e)}return o},f=function(t,n,r){var e=c(n,r,!1);return void 0!==e&&e.has(t)},a=function(t,n,r){var e=c(n,r,!1);return void 0===e?void 0:e.get(t)},s=function(t,n,r,e){c(r,e,!0).set(t,n)},l=function(t,n){var r=c(t,n,!1),e=[];return r&&r.forEach(function(t,n){e.push(n)}),e},h=function(t){return void 0===t||"symbol"==typeof t?t:String(t)},v=function(t){i(i.S,"Reflect",t)};t.exports={store:u,map:c,has:f,get:a,set:s,keys:l,key:h,exp:v}},function(t,n,r){"use strict";if(r(10)){var e=r(69),i=r(3),o=r(4),u=r(1),c=r(127),f=r(152),a=r(53),s=r(68),l=r(66),h=r(27),v=r(73),p=r(67),d=r(16),y=r(75),g=r(50),b=r(24),m=r(180),x=r(114),w=r(6),S=r(17),_=r(137),O=r(70),E=r(32),P=r(71).f,j=r(154),F=r(76),M=r(7),A=r(48),N=r(117),T=r(146),I=r(155),k=r(80),L=r(123),R=r(74),C=r(130),D=r(160),U=r(11),W=r(31),G=U.f,B=W.f,V=i.RangeError,z=i.TypeError,q=i.Uint8Array,K="ArrayBuffer",J="Shared"+K,Y="BYTES_PER_ELEMENT",H="prototype",$=Array[H],X=f.ArrayBuffer,Q=f.DataView,Z=A(0),tt=A(2),nt=A(3),rt=A(4),et=A(5),it=A(6),ot=N(!0),ut=N(!1),ct=I.values,ft=I.keys,at=I.entries,st=$.lastIndexOf,lt=$.reduce,ht=$.reduceRight,vt=$.join,pt=$.sort,dt=$.slice,yt=$.toString,gt=$.toLocaleString,bt=M("iterator"),mt=M("toStringTag"),xt=F("typed_constructor"),wt=F("def_constructor"),St=c.CONSTR,_t=c.TYPED,Ot=c.VIEW,Et="Wrong length!",Pt=A(1,function(t,n){return Tt(T(t,t[wt]),n)}),jt=o(function(){return 1===new q(new Uint16Array([1]).buffer)[0]}),Ft=!!q&&!!q[H].set&&o(function(){new q(1).set({})}),Mt=function(t,n){if(void 0===t)throw z(Et);var r=+t,e=d(t);if(n&&!m(r,e))throw V(Et);return e},At=function(t,n){var r=p(t);if(r<0||r%n)throw V("Wrong offset!");return r},Nt=function(t){if(w(t)&&_t in t)return t;throw z(t+" is not a typed array!")},Tt=function(t,n){if(!(w(t)&&xt in t))throw z("It is not a typed array constructor!");return new t(n)},It=function(t,n){return kt(T(t,t[wt]),n)},kt=function(t,n){for(var r=0,e=n.length,i=Tt(t,e);e>r;)i[r]=n[r++];return i},Lt=function(t,n,r){G(t,n,{get:function(){return this._d[r]}})},Rt=function(t){var n,r,e,i,o,u,c=S(t),f=arguments.length,s=f>1?arguments[1]:void 0,l=void 0!==s,h=j(c);if(void 0!=h&&!_(h)){for(u=h.call(c),e=[],n=0;!(o=u.next()).done;n++)e.push(o.value);c=e}for(l&&f>2&&(s=a(s,arguments[2],2)),n=0,r=d(c.length),i=Tt(this,r);r>n;n++)i[n]=l?s(c[n],n):c[n];return i},Ct=function(){for(var t=0,n=arguments.length,r=Tt(this,n);n>t;)r[t]=arguments[t++];return r},Dt=!!q&&o(function(){gt.call(new q(1))}),Ut=function(){return gt.apply(Dt?dt.call(Nt(this)):Nt(this),arguments)},Wt={copyWithin:function(t,n){return D.call(Nt(this),t,n,arguments.length>2?arguments[2]:void 0)},every:function(t){return rt(Nt(this),t,arguments.length>1?arguments[1]:void 0)},fill:function(t){return C.apply(Nt(this),arguments)},filter:function(t){return It(this,tt(Nt(this),t,arguments.length>1?arguments[1]:void 0))},find:function(t){return et(Nt(this),t,arguments.length>1?arguments[1]:void 0)},findIndex:function(t){return it(Nt(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function(t){Z(Nt(this),t,arguments.length>1?arguments[1]:void 0)},indexOf:function(t){return ut(Nt(this),t,arguments.length>1?arguments[1]:void 0)},includes:function(t){return ot(Nt(this),t,arguments.length>1?arguments[1]:void 0)},join:function(t){return vt.apply(Nt(this),arguments)},lastIndexOf:function(t){return st.apply(Nt(this),arguments)},map:function(t){return Pt(Nt(this),t,arguments.length>1?arguments[1]:void 0)},reduce:function(t){return lt.apply(Nt(this),arguments)},reduceRight:function(t){return ht.apply(Nt(this),arguments)},reverse:function(){for(var t,n=this,r=Nt(n).length,e=Math.floor(r/2),i=0;i<e;)t=n[i],n[i++]=n[--r],n[r]=t;return n},some:function(t){return nt(Nt(this),t,arguments.length>1?arguments[1]:void 0)},sort:function(t){return pt.call(Nt(this),t)},subarray:function(t,n){var r=Nt(this),e=r.length,i=y(t,e);return new(T(r,r[wt]))(r.buffer,r.byteOffset+i*r.BYTES_PER_ELEMENT,d((void 0===n?e:y(n,e))-i))}},Gt=function(t,n){return It(this,dt.call(Nt(this),t,n))},Bt=function(t){Nt(this);var n=At(arguments[1],1),r=this.length,e=S(t),i=d(e.length),o=0;if(i+n>r)throw V(Et);for(;o<i;)this[n+o]=e[o++]},Vt={entries:function(){return at.call(Nt(this))},keys:function(){return ft.call(Nt(this))},values:function(){return ct.call(Nt(this))}},zt=function(t,n){return w(t)&&t[_t]&&"symbol"!=typeof n&&n in t&&String(+n)==String(n)},qt=function(t,n){return zt(t,n=g(n,!0))?l(2,t[n]):B(t,n)},Kt=function(t,n,r){return!(zt(t,n=g(n,!0))&&w(r)&&b(r,"value"))||b(r,"get")||b(r,"set")||r.configurable||b(r,"writable")&&!r.writable||b(r,"enumerable")&&!r.enumerable?G(t,n,r):(t[n]=r.value,t)};St||(W.f=qt,U.f=Kt),u(u.S+u.F*!St,"Object",{getOwnPropertyDescriptor:qt,defineProperty:Kt}),o(function(){yt.call({})})&&(yt=gt=function(){return vt.call(this)});var Jt=v({},Wt);v(Jt,Vt),h(Jt,bt,Vt.values),v(Jt,{slice:Gt,set:Bt,constructor:function(){},toString:yt,toLocaleString:Ut}),Lt(Jt,"buffer","b"),Lt(Jt,"byteOffset","o"),Lt(Jt,"byteLength","l"),Lt(Jt,"length","e"),G(Jt,mt,{get:function(){return this[_t]}}),t.exports=function(t,n,r,f){f=!!f;var a=t+(f?"Clamped":"")+"Array",l="Uint8Array"!=a,v="get"+t,p="set"+t,y=i[a],g=y||{},b=y&&E(y),m=!y||!c.ABV,S={},_=y&&y[H],j=function(t,r){var e=t._d;return e.v[v](r*n+e.o,jt)},F=function(t,r,e){var i=t._d;f&&(e=(e=Math.round(e))<0?0:e>255?255:255&e),i.v[p](r*n+i.o,e,jt)},M=function(t,n){G(t,n,{get:function(){return j(this,n)},set:function(t){return F(this,n,t)},enumerable:!0})};m?(y=r(function(t,r,e,i){s(t,y,a,"_d");var o,u,c,f,l=0,v=0;if(w(r)){if(!(r instanceof X||(f=x(r))==K||f==J))return _t in r?kt(y,r):Rt.call(y,r);o=r,v=At(e,n);var p=r.byteLength;if(void 0===i){if(p%n)throw V(Et);if((u=p-v)<0)throw V(Et)}else if((u=d(i)*n)+v>p)throw V(Et);c=u/n}else c=Mt(r,!0),u=c*n,o=new X(u);for(h(t,"_d",{b:o,o:v,l:u,e:c,v:new Q(o)});l<c;)M(t,l++)}),_=y[H]=O(Jt),h(_,"constructor",y)):L(function(t){new y(null),new y(t)},!0)||(y=r(function(t,r,e,i){s(t,y,a);var o;return w(r)?r instanceof X||(o=x(r))==K||o==J?void 0!==i?new g(r,At(e,n),i):void 0!==e?new g(r,At(e,n)):new g(r):_t in r?kt(y,r):Rt.call(y,r):new g(Mt(r,l))}),Z(b!==Function.prototype?P(g).concat(P(b)):P(g),function(t){t in y||h(y,t,g[t])}),y[H]=_,e||(_.constructor=y));var A=_[bt],N=!!A&&("values"==A.name||void 0==A.name),T=Vt.values;h(y,xt,!0),h(_,_t,a),h(_,Ot,!0),h(_,wt,y),(f?new y(1)[mt]==a:mt in _)||G(_,mt,{get:function(){return a}}),S[a]=y,u(u.G+u.W+u.F*(y!=g),S),u(u.S,a,{BYTES_PER_ELEMENT:n,from:Rt,of:Ct}),Y in _||h(_,Y,n),u(u.P,a,Wt),R(a),u(u.P+u.F*Ft,a,{set:Bt}),u(u.P+u.F*!N,a,Vt),u(u.P+u.F*(_.toString!=yt),a,{toString:yt}),u(u.P+u.F*o(function(){new y(1).slice()}),a,{slice:Gt}),u(u.P+u.F*(o(function(){return[1,2].toLocaleString()!=new y([1,2]).toLocaleString()})||!o(function(){_.toLocaleString.call([1,2])})),a,{toLocaleString:Ut}),k[a]=N?A:T,e||N||h(_,bt,T)}}else t.exports=function(){}},function(t,n){var r={}.toString;t.exports=function(t){return r.call(t).slice(8,-1)}},function(t,n,r){var e=r(21),i=r(5).document,o=e(i)&&e(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,n,r){t.exports=!r(12)&&!r(18)(function(){return 7!=Object.defineProperty(r(57)("div"),"a",{get:function(){return 7}}).a})},function(t,n,r){"use strict";var e=r(36),i=r(51),o=r(64),u=r(13),c=r(8),f=r(35),a=r(96),s=r(38),l=r(103),h=r(15)("iterator"),v=!([].keys&&"next"in[].keys()),p="keys",d="values",y=function(){return this};t.exports=function(t,n,r,g,b,m,x){a(r,n,g);var w,S,_,O=function(t){if(!v&&t in F)return F[t];switch(t){case p:case d:return function(){return new r(this,t)}}return function(){return new r(this,t)}},E=n+" Iterator",P=b==d,j=!1,F=t.prototype,M=F[h]||F["@@iterator"]||b&&F[b],A=M||O(b),N=b?P?O("entries"):A:void 0,T="Array"==n?F.entries||M:M;if(T&&(_=l(T.call(new t)))!==Object.prototype&&(s(_,E,!0),e||c(_,h)||u(_,h,y)),P&&M&&M.name!==d&&(j=!0,A=function(){return M.call(this)}),e&&!x||!v&&!j&&F[h]||u(F,h,A),f[n]=A,f[E]=y,b)if(w={values:P?A:O(d),keys:m?A:O(p),entries:N},x)for(S in w)S in F||o(F,S,w[S]);else i(i.P+i.F*(v||j),n,w);return w}},function(t,n,r){var e=r(20),i=r(100),o=r(34),u=r(39)("IE_PROTO"),c=function(){},f="prototype",a=function(){var t,n=r(57)("iframe"),e=o.length;for(n.style.display="none",r(93).appendChild(n),n.src="javascript:",t=n.contentWindow.document,t.open(),t.write("<script>document.F=Object<\/script>"),t.close(),a=t.F;e--;)delete a[f][o[e]];return a()};t.exports=Object.create||function(t,n){var r;return null!==t?(c[f]=e(t),r=new c,c[f]=null,r[u]=t):r=a(),void 0===n?r:i(r,n)}},function(t,n,r){var e=r(63),i=r(34).concat("length","prototype");n.f=Object.getOwnPropertyNames||function(t){return e(t,i)}},function(t,n){n.f=Object.getOwnPropertySymbols},function(t,n,r){var e=r(8),i=r(9),o=r(90)(!1),u=r(39)("IE_PROTO");t.exports=function(t,n){var r,c=i(t),f=0,a=[];for(r in c)r!=u&&e(c,r)&&a.push(r);for(;n.length>f;)e(c,r=n[f++])&&(~o(a,r)||a.push(r));return a}},function(t,n,r){t.exports=r(13)},function(t,n,r){var e=r(76)("meta"),i=r(6),o=r(24),u=r(11).f,c=0,f=Object.isExtensible||function(){return!0},a=!r(4)(function(){return f(Object.preventExtensions({}))}),s=function(t){u(t,e,{value:{i:"O"+ ++c,w:{}}})},l=function(t,n){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!o(t,e)){if(!f(t))return"F";if(!n)return"E";s(t)}return t[e].i},h=function(t,n){if(!o(t,e)){if(!f(t))return!0;if(!n)return!1;s(t)}return t[e].w},v=function(t){return a&&p.NEED&&f(t)&&!o(t,e)&&s(t),t},p=t.exports={KEY:e,NEED:!1,fastKey:l,getWeak:h,onFreeze:v}},function(t,n){t.exports=function(t,n){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:n}}},function(t,n){var r=Math.ceil,e=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?e:r)(t)}},function(t,n){t.exports=function(t,n,r,e){if(!(t instanceof n)||void 0!==e&&e in t)throw TypeError(r+": incorrect invocation!");return t}},function(t,n){t.exports=!1},function(t,n,r){var e=r(2),i=r(173),o=r(133),u=r(145)("IE_PROTO"),c=function(){},f="prototype",a=function(){var t,n=r(132)("iframe"),e=o.length;for(n.style.display="none",r(135).appendChild(n),n.src="javascript:",t=n.contentWindow.document,t.open(),t.write("<script>document.F=Object<\/script>"),t.close(),a=t.F;e--;)delete a[f][o[e]];return a()};t.exports=Object.create||function(t,n){var r;return null!==t?(c[f]=e(t),r=new c,c[f]=null,r[u]=t):r=a(),void 0===n?r:i(r,n)}},function(t,n,r){var e=r(175),i=r(133).concat("length","prototype");n.f=Object.getOwnPropertyNames||function(t){return e(t,i)}},function(t,n,r){var e=r(175),i=r(133);t.exports=Object.keys||function(t){return e(t,i)}},function(t,n,r){var e=r(28);t.exports=function(t,n,r){for(var i in n)e(t,i,n[i],r);return t}},function(t,n,r){"use strict";var e=r(3),i=r(11),o=r(10),u=r(7)("species");t.exports=function(t){var n=e[t];o&&n&&!n[u]&&i.f(n,u,{configurable:!0,get:function(){return this}})}},function(t,n,r){var e=r(67),i=Math.max,o=Math.min;t.exports=function(t,n){return t=e(t),t<0?i(t+n,0):o(t,n)}},function(t,n){var r=0,e=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++r+e).toString(36))}},function(t,n,r){var e=r(33);t.exports=function(t){return Object(e(t))}},function(t,n,r){var e=r(7)("unscopables"),i=Array.prototype;void 0==i[e]&&r(27)(i,e,{}),t.exports=function(t){i[e][t]=!0}},function(t,n,r){var e=r(53),i=r(169),o=r(137),u=r(2),c=r(16),f=r(154),a={},s={},n=t.exports=function(t,n,r,l,h){var v,p,d,y,g=h?function(){return t}:f(t),b=e(r,l,n?2:1),m=0;if("function"!=typeof g)throw TypeError(t+" is not iterable!");if(o(g)){for(v=c(t.length);v>m;m++)if((y=n?b(u(p=t[m])[0],p[1]):b(t[m]))===a||y===s)return y}else for(d=g.call(t);!(p=d.next()).done;)if((y=i(d,b,p.value,n))===a||y===s)return y};n.BREAK=a,n.RETURN=s},function(t,n){t.exports={}},function(t,n,r){var e=r(11).f,i=r(24),o=r(7)("toStringTag");t.exports=function(t,n,r){t&&!i(t=r?t:t.prototype,o)&&e(t,o,{configurable:!0,value:n})}},function(t,n,r){var e=r(1),i=r(46),o=r(4),u=r(150),c="["+u+"]",f="​",a=RegExp("^"+c+c+"*"),s=RegExp(c+c+"*$"),l=function(t,n,r){var i={},c=o(function(){return!!u[t]()||f[t]()!=f}),a=i[t]=c?n(h):u[t];r&&(i[r]=a),e(e.P+e.F*c,"String",i)},h=l.trim=function(t,n){return t=String(i(t)),1&n&&(t=t.replace(a,"")),2&n&&(t=t.replace(s,"")),t};t.exports=l},function(t,n,r){t.exports={default:r(86),__esModule:!0}},function(t,n,r){t.exports={default:r(87),__esModule:!0}},function(t,n,r){"use strict";function e(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0;var i=r(84),o=e(i),u=r(83),c=e(u),f="function"==typeof c.default&&"symbol"==typeof o.default?function(t){return typeof t}:function(t){return t&&"function"==typeof c.default&&t.constructor===c.default&&t!==c.default.prototype?"symbol":typeof t};n.default="function"==typeof c.default&&"symbol"===f(o.default)?function(t){return void 0===t?"undefined":f(t)}:function(t){return t&&"function"==typeof c.default&&t.constructor===c.default&&t!==c.default.prototype?"symbol":void 0===t?"undefined":f(t)}},function(t,n,r){r(110),r(108),r(111),r(112),t.exports=r(25).Symbol},function(t,n,r){r(109),r(113),t.exports=r(44).f("iterator")},function(t,n){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,n){t.exports=function(){}},function(t,n,r){var e=r(9),i=r(106),o=r(105);t.exports=function(t){return function(n,r,u){var c,f=e(n),a=i(f.length),s=o(u,a);if(t&&r!=r){for(;a>s;)if((c=f[s++])!=c)return!0}else for(;a>s;s++)if((t||s in f)&&f[s]===r)return t||s||0;return!t&&-1}}},function(t,n,r){var e=r(88);t.exports=function(t,n,r){if(e(t),void 0===n)return t;switch(r){case 1:return function(r){return t.call(n,r)};case 2:return function(r,e){return t.call(n,r,e)};case 3:return function(r,e,i){return t.call(n,r,e,i)}}return function(){return t.apply(n,arguments)}}},function(t,n,r){var e=r(19),i=r(62),o=r(37);t.exports=function(t){var n=e(t),r=i.f;if(r)for(var u,c=r(t),f=o.f,a=0;c.length>a;)f.call(t,u=c[a++])&&n.push(u);return n}},function(t,n,r){t.exports=r(5).document&&document.documentElement},function(t,n,r){var e=r(56);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==e(t)?t.split(""):Object(t)}},function(t,n,r){var e=r(56);t.exports=Array.isArray||function(t){return"Array"==e(t)}},function(t,n,r){"use strict";var e=r(60),i=r(22),o=r(38),u={};r(13)(u,r(15)("iterator"),function(){return this}),t.exports=function(t,n,r){t.prototype=e(u,{next:i(1,r)}),o(t,n+" Iterator")}},function(t,n){t.exports=function(t,n){return{value:n,done:!!t}}},function(t,n,r){var e=r(19),i=r(9);t.exports=function(t,n){for(var r,o=i(t),u=e(o),c=u.length,f=0;c>f;)if(o[r=u[f++]]===n)return r}},function(t,n,r){var e=r(23)("meta"),i=r(21),o=r(8),u=r(14).f,c=0,f=Object.isExtensible||function(){return!0},a=!r(18)(function(){return f(Object.preventExtensions({}))}),s=function(t){u(t,e,{value:{i:"O"+ ++c,w:{}}})},l=function(t,n){if(!i(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!o(t,e)){if(!f(t))return"F";if(!n)return"E";s(t)}return t[e].i},h=function(t,n){if(!o(t,e)){if(!f(t))return!0;if(!n)return!1;s(t)}return t[e].w},v=function(t){return a&&p.NEED&&f(t)&&!o(t,e)&&s(t),t},p=t.exports={KEY:e,NEED:!1,fastKey:l,getWeak:h,onFreeze:v}},function(t,n,r){var e=r(14),i=r(20),o=r(19);t.exports=r(12)?Object.defineProperties:function(t,n){i(t);for(var r,u=o(n),c=u.length,f=0;c>f;)e.f(t,r=u[f++],n[r]);return t}},function(t,n,r){var e=r(37),i=r(22),o=r(9),u=r(42),c=r(8),f=r(58),a=Object.getOwnPropertyDescriptor;n.f=r(12)?a:function(t,n){if(t=o(t),n=u(n,!0),f)try{return a(t,n)}catch(t){}if(c(t,n))return i(!e.f.call(t,n),t[n])}},function(t,n,r){var e=r(9),i=r(61).f,o={}.toString,u="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],c=function(t){try{return i(t)}catch(t){return u.slice()}};t.exports.f=function(t){return u&&"[object Window]"==o.call(t)?c(t):i(e(t))}},function(t,n,r){var e=r(8),i=r(77),o=r(39)("IE_PROTO"),u=Object.prototype;t.exports=Object.getPrototypeOf||function(t){return t=i(t),e(t,o)?t[o]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?u:null}},function(t,n,r){var e=r(41),i=r(33);t.exports=function(t){return function(n,r){var o,u,c=String(i(n)),f=e(r),a=c.length;return f<0||f>=a?t?"":void 0:(o=c.charCodeAt(f),o<55296||o>56319||f+1===a||(u=c.charCodeAt(f+1))<56320||u>57343?t?c.charAt(f):o:t?c.slice(f,f+2):u-56320+(o-55296<<10)+65536)}}},function(t,n,r){var e=r(41),i=Math.max,o=Math.min;t.exports=function(t,n){return t=e(t),t<0?i(t+n,0):o(t,n)}},function(t,n,r){var e=r(41),i=Math.min;t.exports=function(t){return t>0?i(e(t),9007199254740991):0}},function(t,n,r){"use strict";var e=r(89),i=r(97),o=r(35),u=r(9);t.exports=r(59)(Array,"Array",function(t,n){this._t=u(t),this._i=0,this._k=n},function(){var t=this._t,n=this._k,r=this._i++;return!t||r>=t.length?(this._t=void 0,i(1)):"keys"==n?i(0,r):"values"==n?i(0,t[r]):i(0,[r,t[r]])},"values"),o.Arguments=o.Array,e("keys"),e("values"),e("entries")},function(t,n){},function(t,n,r){"use strict";var e=r(104)(!0);r(59)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,n=this._t,r=this._i;return r>=n.length?{value:void 0,done:!0}:(t=e(n,r),this._i+=t.length,{value:t,done:!1})})},function(t,n,r){"use strict";var e=r(5),i=r(8),o=r(12),u=r(51),c=r(64),f=r(99).KEY,a=r(18),s=r(40),l=r(38),h=r(23),v=r(15),p=r(44),d=r(43),y=r(98),g=r(92),b=r(95),m=r(20),x=r(9),w=r(42),S=r(22),_=r(60),O=r(102),E=r(101),P=r(14),j=r(19),F=E.f,M=P.f,A=O.f,N=e.Symbol,T=e.JSON,I=T&&T.stringify,k="prototype",L=v("_hidden"),R=v("toPrimitive"),C={}.propertyIsEnumerable,D=s("symbol-registry"),U=s("symbols"),W=s("op-symbols"),G=Object[k],B="function"==typeof N,V=e.QObject,z=!V||!V[k]||!V[k].findChild,q=o&&a(function(){return 7!=_(M({},"a",{get:function(){return M(this,"a",{value:7}).a}})).a})?function(t,n,r){var e=F(G,n);e&&delete G[n],M(t,n,r),e&&t!==G&&M(G,n,e)}:M,K=function(t){var n=U[t]=_(N[k]);return n._k=t,n},J=B&&"symbol"==typeof N.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof N},Y=function(t,n,r){return t===G&&Y(W,n,r),m(t),n=w(n,!0),m(r),i(U,n)?(r.enumerable?(i(t,L)&&t[L][n]&&(t[L][n]=!1),r=_(r,{enumerable:S(0,!1)})):(i(t,L)||M(t,L,S(1,{})),t[L][n]=!0),q(t,n,r)):M(t,n,r)},H=function(t,n){m(t);for(var r,e=g(n=x(n)),i=0,o=e.length;o>i;)Y(t,r=e[i++],n[r]);return t},$=function(t,n){return void 0===n?_(t):H(_(t),n)},X=function(t){var n=C.call(this,t=w(t,!0));return!(this===G&&i(U,t)&&!i(W,t))&&(!(n||!i(this,t)||!i(U,t)||i(this,L)&&this[L][t])||n)},Q=function(t,n){if(t=x(t),n=w(n,!0),t!==G||!i(U,n)||i(W,n)){var r=F(t,n);return!r||!i(U,n)||i(t,L)&&t[L][n]||(r.enumerable=!0),r}},Z=function(t){for(var n,r=A(x(t)),e=[],o=0;r.length>o;)i(U,n=r[o++])||n==L||n==f||e.push(n);return e},tt=function(t){for(var n,r=t===G,e=A(r?W:x(t)),o=[],u=0;e.length>u;)!i(U,n=e[u++])||r&&!i(G,n)||o.push(U[n]);return o};B||(N=function(){if(this instanceof N)throw TypeError("Symbol is not a constructor!");var t=h(arguments.length>0?arguments[0]:void 0),n=function(r){this===G&&n.call(W,r),i(this,L)&&i(this[L],t)&&(this[L][t]=!1),q(this,t,S(1,r))};return o&&z&&q(G,t,{configurable:!0,set:n}),K(t)},c(N[k],"toString",function(){return this._k}),E.f=Q,P.f=Y,r(61).f=O.f=Z,r(37).f=X,r(62).f=tt,o&&!r(36)&&c(G,"propertyIsEnumerable",X,!0),p.f=function(t){return K(v(t))}),u(u.G+u.W+u.F*!B,{Symbol:N});for(var nt="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),rt=0;nt.length>rt;)v(nt[rt++]);for(var nt=j(v.store),rt=0;nt.length>rt;)d(nt[rt++]);u(u.S+u.F*!B,"Symbol",{for:function(t){return i(D,t+="")?D[t]:D[t]=N(t)},keyFor:function(t){if(J(t))return y(D,t);throw TypeError(t+" is not a symbol!")},useSetter:function(){z=!0},useSimple:function(){z=!1}}),u(u.S+u.F*!B,"Object",{create:$,defineProperty:Y,defineProperties:H,getOwnPropertyDescriptor:Q,getOwnPropertyNames:Z,getOwnPropertySymbols:tt}),T&&u(u.S+u.F*(!B||a(function(){var t=N();return"[null]"!=I([t])||"{}"!=I({a:t})||"{}"!=I(Object(t))})),"JSON",{stringify:function(t){if(void 0!==t&&!J(t)){for(var n,r,e=[t],i=1;arguments.length>i;)e.push(arguments[i++]);return n=e[1],"function"==typeof n&&(r=n),!r&&b(n)||(n=function(t,n){if(r&&(n=r.call(this,t,n)),!J(n))return n}),e[1]=n,I.apply(T,e)}}}),N[k][R]||r(13)(N[k],R,N[k].valueOf),l(N,"Symbol"),l(Math,"Math",!0),l(e.JSON,"JSON",!0)},function(t,n,r){r(43)("asyncIterator")},function(t,n,r){r(43)("observable")},function(t,n,r){r(107);for(var e=r(5),i=r(13),o=r(35),u=r(15)("toStringTag"),c=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],f=0;f<5;f++){var a=c[f],s=e[a],l=s&&s.prototype;l&&!l[u]&&i(l,u,a),o[a]=o.Array}},function(t,n,r){var e=r(45),i=r(7)("toStringTag"),o="Arguments"==e(function(){return arguments}()),u=function(t,n){try{return t[n]}catch(t){}};t.exports=function(t){var n,r,c;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=u(n=Object(t),i))?r:o?e(n):"Object"==(c=e(n))&&"function"==typeof n.callee?"Arguments":c}},function(t,n,r){var e=r(45);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==e(t)?t.split(""):Object(t)}},function(t,n){n.f={}.propertyIsEnumerable},function(t,n,r){var e=r(30),i=r(16),o=r(75);t.exports=function(t){return function(n,r,u){var c,f=e(n),a=i(f.length),s=o(u,a);if(t&&r!=r){for(;a>s;)if((c=f[s++])!=c)return!0}else for(;a>s;s++)if((t||s in f)&&f[s]===r)return t||s||0;return!t&&-1}}},function(t,n,r){"use strict";var e=r(3),i=r(1),o=r(28),u=r(73),c=r(65),f=r(79),a=r(68),s=r(6),l=r(4),h=r(123),v=r(81),p=r(136);t.exports=function(t,n,r,d,y,g){var b=e[t],m=b,x=y?"set":"add",w=m&&m.prototype,S={},_=function(t){var n=w[t];o(w,t,"delete"==t?function(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"has"==t?function(t){return!(g&&!s(t))&&n.call(this,0===t?0:t)}:"get"==t?function(t){return g&&!s(t)?void 0:n.call(this,0===t?0:t)}:"add"==t?function(t){return n.call(this,0===t?0:t),this}:function(t,r){return n.call(this,0===t?0:t,r),this})};if("function"==typeof m&&(g||w.forEach&&!l(function(){(new m).entries().next()}))){var O=new m,E=O[x](g?{}:-0,1)!=O,P=l(function(){O.has(1)}),j=h(function(t){new m(t)}),F=!g&&l(function(){for(var t=new m,n=5;n--;)t[x](n,n);return!t.has(-0)});j||(m=n(function(n,r){a(n,m,t);var e=p(new b,n,m);return void 0!=r&&f(r,y,e[x],e),e}),m.prototype=w,w.constructor=m),(P||F)&&(_("delete"),_("has"),y&&_("get")),(F||E)&&_(x),g&&w.clear&&delete w.clear}else m=d.getConstructor(n,t,y,x),u(m.prototype,r),c.NEED=!0;return v(m,t),S[t]=m,i(i.G+i.W+i.F*(m!=b),S),g||d.setStrong(m,t,y),m}},function(t,n,r){"use strict";var e=r(27),i=r(28),o=r(4),u=r(46),c=r(7);t.exports=function(t,n,r){var f=c(t),a=r(u,f,""[t]),s=a[0],l=a[1];o(function(){var n={};return n[f]=function(){return 7},7!=""[t](n)})&&(i(String.prototype,t,s),e(RegExp.prototype,f,2==n?function(t,n){return l.call(t,this,n)}:function(t){return l.call(t,this)}))}
},function(t,n,r){"use strict";var e=r(2);t.exports=function(){var t=e(this),n="";return t.global&&(n+="g"),t.ignoreCase&&(n+="i"),t.multiline&&(n+="m"),t.unicode&&(n+="u"),t.sticky&&(n+="y"),n}},function(t,n){t.exports=function(t,n,r){var e=void 0===r;switch(n.length){case 0:return e?t():t.call(r);case 1:return e?t(n[0]):t.call(r,n[0]);case 2:return e?t(n[0],n[1]):t.call(r,n[0],n[1]);case 3:return e?t(n[0],n[1],n[2]):t.call(r,n[0],n[1],n[2]);case 4:return e?t(n[0],n[1],n[2],n[3]):t.call(r,n[0],n[1],n[2],n[3])}return t.apply(r,n)}},function(t,n,r){var e=r(6),i=r(45),o=r(7)("match");t.exports=function(t){var n;return e(t)&&(void 0!==(n=t[o])?!!n:"RegExp"==i(t))}},function(t,n,r){var e=r(7)("iterator"),i=!1;try{var o=[7][e]();o.return=function(){i=!0},Array.from(o,function(){throw 2})}catch(t){}t.exports=function(t,n){if(!n&&!i)return!1;var r=!1;try{var o=[7],u=o[e]();u.next=function(){return{done:r=!0}},o[e]=function(){return u},t(o)}catch(t){}return r}},function(t,n,r){t.exports=r(69)||!r(4)(function(){var t=Math.random();__defineSetter__.call(null,t,function(){}),delete r(3)[t]})},function(t,n){n.f=Object.getOwnPropertySymbols},function(t,n,r){var e=r(3),i="__core-js_shared__",o=e[i]||(e[i]={});t.exports=function(t){return o[t]||(o[t]={})}},function(t,n,r){for(var e,i=r(3),o=r(27),u=r(76),c=u("typed_array"),f=u("view"),a=!(!i.ArrayBuffer||!i.DataView),s=a,l=0,h="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");l<9;)(e=i[h[l++]])?(o(e.prototype,c,!0),o(e.prototype,f,!0)):s=!1;t.exports={ABV:a,CONSTR:s,TYPED:c,VIEW:f}},function(t,n){"use strict";var r={versions:function(){var t=window.navigator.userAgent;return{trident:t.indexOf("Trident")>-1,presto:t.indexOf("Presto")>-1,webKit:t.indexOf("AppleWebKit")>-1,gecko:t.indexOf("Gecko")>-1&&-1==t.indexOf("KHTML"),mobile:!!t.match(/AppleWebKit.*Mobile.*/),ios:!!t.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),android:t.indexOf("Android")>-1||t.indexOf("Linux")>-1,iPhone:t.indexOf("iPhone")>-1||t.indexOf("Mac")>-1,iPad:t.indexOf("iPad")>-1,webApp:-1==t.indexOf("Safari"),weixin:-1==t.indexOf("MicroMessenger")}}()};t.exports=r},function(t,n,r){"use strict";var e=r(85),i=function(t){return t&&t.__esModule?t:{default:t}}(e),o=function(){function t(t,n,e){return n||e?String.fromCharCode(n||e):r[t]||t}function n(t){return e[t]}var r={"&quot;":'"',"&lt;":"<","&gt;":">","&amp;":"&","&nbsp;":" "},e={};for(var u in r)e[r[u]]=u;return r["&apos;"]="'",e["'"]="&#39;",{encode:function(t){return t?(""+t).replace(/['<> "&]/g,n).replace(/\r?\n/g,"<br/>").replace(/\s/g,"&nbsp;"):""},decode:function(n){return n?(""+n).replace(/<br\s*\/?>/gi,"\n").replace(/&quot;|&lt;|&gt;|&amp;|&nbsp;|&apos;|&#(\d+);|&#(\d+)/g,t).replace(/\u00a0/g," "):""},encodeBase16:function(t){if(!t)return t;t+="";for(var n=[],r=0,e=t.length;e>r;r++)n.push(t.charCodeAt(r).toString(16).toUpperCase());return n.join("")},encodeBase16forJSON:function(t){if(!t)return t;t=t.replace(/[\u4E00-\u9FBF]/gi,function(t){return escape(t).replace("%u","\\u")});for(var n=[],r=0,e=t.length;e>r;r++)n.push(t.charCodeAt(r).toString(16).toUpperCase());return n.join("")},decodeBase16:function(t){if(!t)return t;t+="";for(var n=[],r=0,e=t.length;e>r;r+=2)n.push(String.fromCharCode("0x"+t.slice(r,r+2)));return n.join("")},encodeObject:function(t){if(t instanceof Array)for(var n=0,r=t.length;r>n;n++)t[n]=o.encodeObject(t[n]);else if("object"==(void 0===t?"undefined":(0,i.default)(t)))for(var e in t)t[e]=o.encodeObject(t[e]);else if("string"==typeof t)return o.encode(t);return t},loadScript:function(t){var n=document.createElement("script");document.getElementsByTagName("body")[0].appendChild(n),n.setAttribute("src",t)},addLoadEvent:function(t){var n=window.onload;"function"!=typeof window.onload?window.onload=t:window.onload=function(){n(),t()}}}}();t.exports=o},function(t,n,r){"use strict";var e=r(17),i=r(75),o=r(16);t.exports=function(t){for(var n=e(this),r=o(n.length),u=arguments.length,c=i(u>1?arguments[1]:void 0,r),f=u>2?arguments[2]:void 0,a=void 0===f?r:i(f,r);a>c;)n[c++]=t;return n}},function(t,n,r){"use strict";var e=r(11),i=r(66);t.exports=function(t,n,r){n in t?e.f(t,n,i(0,r)):t[n]=r}},function(t,n,r){var e=r(6),i=r(3).document,o=e(i)&&e(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,n){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,n,r){var e=r(7)("match");t.exports=function(t){var n=/./;try{"/./"[t](n)}catch(r){try{return n[e]=!1,!"/./"[t](n)}catch(t){}}return!0}},function(t,n,r){t.exports=r(3).document&&document.documentElement},function(t,n,r){var e=r(6),i=r(144).set;t.exports=function(t,n,r){var o,u=n.constructor;return u!==r&&"function"==typeof u&&(o=u.prototype)!==r.prototype&&e(o)&&i&&i(t,o),t}},function(t,n,r){var e=r(80),i=r(7)("iterator"),o=Array.prototype;t.exports=function(t){return void 0!==t&&(e.Array===t||o[i]===t)}},function(t,n,r){var e=r(45);t.exports=Array.isArray||function(t){return"Array"==e(t)}},function(t,n,r){"use strict";var e=r(70),i=r(66),o=r(81),u={};r(27)(u,r(7)("iterator"),function(){return this}),t.exports=function(t,n,r){t.prototype=e(u,{next:i(1,r)}),o(t,n+" Iterator")}},function(t,n,r){"use strict";var e=r(69),i=r(1),o=r(28),u=r(27),c=r(24),f=r(80),a=r(139),s=r(81),l=r(32),h=r(7)("iterator"),v=!([].keys&&"next"in[].keys()),p="keys",d="values",y=function(){return this};t.exports=function(t,n,r,g,b,m,x){a(r,n,g);var w,S,_,O=function(t){if(!v&&t in F)return F[t];switch(t){case p:case d:return function(){return new r(this,t)}}return function(){return new r(this,t)}},E=n+" Iterator",P=b==d,j=!1,F=t.prototype,M=F[h]||F["@@iterator"]||b&&F[b],A=M||O(b),N=b?P?O("entries"):A:void 0,T="Array"==n?F.entries||M:M;if(T&&(_=l(T.call(new t)))!==Object.prototype&&(s(_,E,!0),e||c(_,h)||u(_,h,y)),P&&M&&M.name!==d&&(j=!0,A=function(){return M.call(this)}),e&&!x||!v&&!j&&F[h]||u(F,h,A),f[n]=A,f[E]=y,b)if(w={values:P?A:O(d),keys:m?A:O(p),entries:N},x)for(S in w)S in F||o(F,S,w[S]);else i(i.P+i.F*(v||j),n,w);return w}},function(t,n){var r=Math.expm1;t.exports=!r||r(10)>22025.465794806718||r(10)<22025.465794806718||-2e-17!=r(-2e-17)?function(t){return 0==(t=+t)?t:t>-1e-6&&t<1e-6?t+t*t/2:Math.exp(t)-1}:r},function(t,n){t.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:t<0?-1:1}},function(t,n,r){var e=r(3),i=r(151).set,o=e.MutationObserver||e.WebKitMutationObserver,u=e.process,c=e.Promise,f="process"==r(45)(u);t.exports=function(){var t,n,r,a=function(){var e,i;for(f&&(e=u.domain)&&e.exit();t;){i=t.fn,t=t.next;try{i()}catch(e){throw t?r():n=void 0,e}}n=void 0,e&&e.enter()};if(f)r=function(){u.nextTick(a)};else if(o){var s=!0,l=document.createTextNode("");new o(a).observe(l,{characterData:!0}),r=function(){l.data=s=!s}}else if(c&&c.resolve){var h=c.resolve();r=function(){h.then(a)}}else r=function(){i.call(e,a)};return function(e){var i={fn:e,next:void 0};n&&(n.next=i),t||(t=i,r()),n=i}}},function(t,n,r){var e=r(6),i=r(2),o=function(t,n){if(i(t),!e(n)&&null!==n)throw TypeError(n+": can't set as prototype!")};t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,n,e){try{e=r(53)(Function.call,r(31).f(Object.prototype,"__proto__").set,2),e(t,[]),n=!(t instanceof Array)}catch(t){n=!0}return function(t,r){return o(t,r),n?t.__proto__=r:e(t,r),t}}({},!1):void 0),check:o}},function(t,n,r){var e=r(126)("keys"),i=r(76);t.exports=function(t){return e[t]||(e[t]=i(t))}},function(t,n,r){var e=r(2),i=r(26),o=r(7)("species");t.exports=function(t,n){var r,u=e(t).constructor;return void 0===u||void 0==(r=e(u)[o])?n:i(r)}},function(t,n,r){var e=r(67),i=r(46);t.exports=function(t){return function(n,r){var o,u,c=String(i(n)),f=e(r),a=c.length;return f<0||f>=a?t?"":void 0:(o=c.charCodeAt(f),o<55296||o>56319||f+1===a||(u=c.charCodeAt(f+1))<56320||u>57343?t?c.charAt(f):o:t?c.slice(f,f+2):u-56320+(o-55296<<10)+65536)}}},function(t,n,r){var e=r(122),i=r(46);t.exports=function(t,n,r){if(e(n))throw TypeError("String#"+r+" doesn't accept regex!");return String(i(t))}},function(t,n,r){"use strict";var e=r(67),i=r(46);t.exports=function(t){var n=String(i(this)),r="",o=e(t);if(o<0||o==1/0)throw RangeError("Count can't be negative");for(;o>0;(o>>>=1)&&(n+=n))1&o&&(r+=n);return r}},function(t,n){t.exports="\t\n\v\f\r   ᠎             　\u2028\u2029\ufeff"},function(t,n,r){var e,i,o,u=r(53),c=r(121),f=r(135),a=r(132),s=r(3),l=s.process,h=s.setImmediate,v=s.clearImmediate,p=s.MessageChannel,d=0,y={},g="onreadystatechange",b=function(){var t=+this;if(y.hasOwnProperty(t)){var n=y[t];delete y[t],n()}},m=function(t){b.call(t.data)};h&&v||(h=function(t){for(var n=[],r=1;arguments.length>r;)n.push(arguments[r++]);return y[++d]=function(){c("function"==typeof t?t:Function(t),n)},e(d),d},v=function(t){delete y[t]},"process"==r(45)(l)?e=function(t){l.nextTick(u(b,t,1))}:p?(i=new p,o=i.port2,i.port1.onmessage=m,e=u(o.postMessage,o,1)):s.addEventListener&&"function"==typeof postMessage&&!s.importScripts?(e=function(t){s.postMessage(t+"","*")},s.addEventListener("message",m,!1)):e=g in a("script")?function(t){f.appendChild(a("script"))[g]=function(){f.removeChild(this),b.call(t)}}:function(t){setTimeout(u(b,t,1),0)}),t.exports={set:h,clear:v}},function(t,n,r){"use strict";var e=r(3),i=r(10),o=r(69),u=r(127),c=r(27),f=r(73),a=r(4),s=r(68),l=r(67),h=r(16),v=r(71).f,p=r(11).f,d=r(130),y=r(81),g="ArrayBuffer",b="DataView",m="prototype",x="Wrong length!",w="Wrong index!",S=e[g],_=e[b],O=e.Math,E=e.RangeError,P=e.Infinity,j=S,F=O.abs,M=O.pow,A=O.floor,N=O.log,T=O.LN2,I="buffer",k="byteLength",L="byteOffset",R=i?"_b":I,C=i?"_l":k,D=i?"_o":L,U=function(t,n,r){var e,i,o,u=Array(r),c=8*r-n-1,f=(1<<c)-1,a=f>>1,s=23===n?M(2,-24)-M(2,-77):0,l=0,h=t<0||0===t&&1/t<0?1:0;for(t=F(t),t!=t||t===P?(i=t!=t?1:0,e=f):(e=A(N(t)/T),t*(o=M(2,-e))<1&&(e--,o*=2),t+=e+a>=1?s/o:s*M(2,1-a),t*o>=2&&(e++,o/=2),e+a>=f?(i=0,e=f):e+a>=1?(i=(t*o-1)*M(2,n),e+=a):(i=t*M(2,a-1)*M(2,n),e=0));n>=8;u[l++]=255&i,i/=256,n-=8);for(e=e<<n|i,c+=n;c>0;u[l++]=255&e,e/=256,c-=8);return u[--l]|=128*h,u},W=function(t,n,r){var e,i=8*r-n-1,o=(1<<i)-1,u=o>>1,c=i-7,f=r-1,a=t[f--],s=127&a;for(a>>=7;c>0;s=256*s+t[f],f--,c-=8);for(e=s&(1<<-c)-1,s>>=-c,c+=n;c>0;e=256*e+t[f],f--,c-=8);if(0===s)s=1-u;else{if(s===o)return e?NaN:a?-P:P;e+=M(2,n),s-=u}return(a?-1:1)*e*M(2,s-n)},G=function(t){return t[3]<<24|t[2]<<16|t[1]<<8|t[0]},B=function(t){return[255&t]},V=function(t){return[255&t,t>>8&255]},z=function(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]},q=function(t){return U(t,52,8)},K=function(t){return U(t,23,4)},J=function(t,n,r){p(t[m],n,{get:function(){return this[r]}})},Y=function(t,n,r,e){var i=+r,o=l(i);if(i!=o||o<0||o+n>t[C])throw E(w);var u=t[R]._b,c=o+t[D],f=u.slice(c,c+n);return e?f:f.reverse()},H=function(t,n,r,e,i,o){var u=+r,c=l(u);if(u!=c||c<0||c+n>t[C])throw E(w);for(var f=t[R]._b,a=c+t[D],s=e(+i),h=0;h<n;h++)f[a+h]=s[o?h:n-h-1]},$=function(t,n){s(t,S,g);var r=+n,e=h(r);if(r!=e)throw E(x);return e};if(u.ABV){if(!a(function(){new S})||!a(function(){new S(.5)})){S=function(t){return new j($(this,t))};for(var X,Q=S[m]=j[m],Z=v(j),tt=0;Z.length>tt;)(X=Z[tt++])in S||c(S,X,j[X]);o||(Q.constructor=S)}var nt=new _(new S(2)),rt=_[m].setInt8;nt.setInt8(0,2147483648),nt.setInt8(1,2147483649),!nt.getInt8(0)&&nt.getInt8(1)||f(_[m],{setInt8:function(t,n){rt.call(this,t,n<<24>>24)},setUint8:function(t,n){rt.call(this,t,n<<24>>24)}},!0)}else S=function(t){var n=$(this,t);this._b=d.call(Array(n),0),this[C]=n},_=function(t,n,r){s(this,_,b),s(t,S,b);var e=t[C],i=l(n);if(i<0||i>e)throw E("Wrong offset!");if(r=void 0===r?e-i:h(r),i+r>e)throw E(x);this[R]=t,this[D]=i,this[C]=r},i&&(J(S,k,"_l"),J(_,I,"_b"),J(_,k,"_l"),J(_,L,"_o")),f(_[m],{getInt8:function(t){return Y(this,1,t)[0]<<24>>24},getUint8:function(t){return Y(this,1,t)[0]},getInt16:function(t){var n=Y(this,2,t,arguments[1]);return(n[1]<<8|n[0])<<16>>16},getUint16:function(t){var n=Y(this,2,t,arguments[1]);return n[1]<<8|n[0]},getInt32:function(t){return G(Y(this,4,t,arguments[1]))},getUint32:function(t){return G(Y(this,4,t,arguments[1]))>>>0},getFloat32:function(t){return W(Y(this,4,t,arguments[1]),23,4)},getFloat64:function(t){return W(Y(this,8,t,arguments[1]),52,8)},setInt8:function(t,n){H(this,1,t,B,n)},setUint8:function(t,n){H(this,1,t,B,n)},setInt16:function(t,n){H(this,2,t,V,n,arguments[2])},setUint16:function(t,n){H(this,2,t,V,n,arguments[2])},setInt32:function(t,n){H(this,4,t,z,n,arguments[2])},setUint32:function(t,n){H(this,4,t,z,n,arguments[2])},setFloat32:function(t,n){H(this,4,t,K,n,arguments[2])},setFloat64:function(t,n){H(this,8,t,q,n,arguments[2])}});y(S,g),y(_,b),c(_[m],u.VIEW,!0),n[g]=S,n[b]=_},function(t,n,r){var e=r(3),i=r(52),o=r(69),u=r(182),c=r(11).f;t.exports=function(t){var n=i.Symbol||(i.Symbol=o?{}:e.Symbol||{});"_"==t.charAt(0)||t in n||c(n,t,{value:u.f(t)})}},function(t,n,r){var e=r(114),i=r(7)("iterator"),o=r(80);t.exports=r(52).getIteratorMethod=function(t){if(void 0!=t)return t[i]||t["@@iterator"]||o[e(t)]}},function(t,n,r){"use strict";var e=r(78),i=r(170),o=r(80),u=r(30);t.exports=r(140)(Array,"Array",function(t,n){this._t=u(t),this._i=0,this._k=n},function(){var t=this._t,n=this._k,r=this._i++;return!t||r>=t.length?(this._t=void 0,i(1)):"keys"==n?i(0,r):"values"==n?i(0,t[r]):i(0,[r,t[r]])},"values"),o.Arguments=o.Array,e("keys"),e("values"),e("entries")},function(t,n){function r(t,n){t.classList?t.classList.add(n):t.className+=" "+n}t.exports=r},function(t,n){function r(t,n){if(t.classList)t.classList.remove(n);else{var r=new RegExp("(^|\\b)"+n.split(" ").join("|")+"(\\b|$)","gi");t.className=t.className.replace(r," ")}}t.exports=r},function(t,n){function r(){throw new Error("setTimeout has not been defined")}function e(){throw new Error("clearTimeout has not been defined")}function i(t){if(s===setTimeout)return setTimeout(t,0);if((s===r||!s)&&setTimeout)return s=setTimeout,setTimeout(t,0);try{return s(t,0)}catch(n){try{return s.call(null,t,0)}catch(n){return s.call(this,t,0)}}}function o(t){if(l===clearTimeout)return clearTimeout(t);if((l===e||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(t);try{return l(t)}catch(n){try{return l.call(null,t)}catch(n){return l.call(this,t)}}}function u(){d&&v&&(d=!1,v.length?p=v.concat(p):y=-1,p.length&&c())}function c(){if(!d){var t=i(u);d=!0;for(var n=p.length;n;){for(v=p,p=[];++y<n;)v&&v[y].run();y=-1,n=p.length}v=null,d=!1,o(t)}}function f(t,n){this.fun=t,this.array=n}function a(){}var s,l,h=t.exports={};!function(){try{s="function"==typeof setTimeout?setTimeout:r}catch(t){s=r}try{l="function"==typeof clearTimeout?clearTimeout:e}catch(t){l=e}}();var v,p=[],d=!1,y=-1;h.nextTick=function(t){var n=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)n[r-1]=arguments[r];p.push(new f(t,n)),1!==p.length||d||i(c)},f.prototype.run=function(){this.fun.apply(null,this.array)},h.title="browser",h.browser=!0,h.env={},h.argv=[],h.version="",h.versions={},h.on=a,h.addListener=a,h.once=a,h.off=a,h.removeListener=a,h.removeAllListeners=a,h.emit=a,h.prependListener=a,h.prependOnceListener=a,h.listeners=function(t){return[]},h.binding=function(t){throw new Error("process.binding is not supported")},h.cwd=function(){return"/"},h.chdir=function(t){throw new Error("process.chdir is not supported")},h.umask=function(){return 0}},function(t,n,r){var e=r(45);t.exports=function(t,n){if("number"!=typeof t&&"Number"!=e(t))throw TypeError(n);return+t}},function(t,n,r){"use strict";var e=r(17),i=r(75),o=r(16);t.exports=[].copyWithin||function(t,n){var r=e(this),u=o(r.length),c=i(t,u),f=i(n,u),a=arguments.length>2?arguments[2]:void 0,s=Math.min((void 0===a?u:i(a,u))-f,u-c),l=1;for(f<c&&c<f+s&&(l=-1,f+=s-1,c+=s-1);s-- >0;)f in r?r[c]=r[f]:delete r[c],c+=l,f+=l;return r}},function(t,n,r){var e=r(79);t.exports=function(t,n){var r=[];return e(t,!1,r.push,r,n),r}},function(t,n,r){var e=r(26),i=r(17),o=r(115),u=r(16);t.exports=function(t,n,r,c,f){e(n);var a=i(t),s=o(a),l=u(a.length),h=f?l-1:0,v=f?-1:1;if(r<2)for(;;){if(h in s){c=s[h],h+=v;break}if(h+=v,f?h<0:l<=h)throw TypeError("Reduce of empty array with no initial value")}for(;f?h>=0:l>h;h+=v)h in s&&(c=n(c,s[h],h,a));return c}},function(t,n,r){"use strict";var e=r(26),i=r(6),o=r(121),u=[].slice,c={},f=function(t,n,r){if(!(n in c)){for(var e=[],i=0;i<n;i++)e[i]="a["+i+"]";c[n]=Function("F,a","return new F("+e.join(",")+")")}return c[n](t,r)};t.exports=Function.bind||function(t){var n=e(this),r=u.call(arguments,1),c=function(){var e=r.concat(u.call(arguments));return this instanceof c?f(n,e.length,e):o(n,e,t)};return i(n.prototype)&&(c.prototype=n.prototype),c}},function(t,n,r){"use strict";var e=r(11).f,i=r(70),o=r(73),u=r(53),c=r(68),f=r(46),a=r(79),s=r(140),l=r(170),h=r(74),v=r(10),p=r(65).fastKey,d=v?"_s":"size",y=function(t,n){var r,e=p(n);if("F"!==e)return t._i[e];for(r=t._f;r;r=r.n)if(r.k==n)return r};t.exports={getConstructor:function(t,n,r,s){var l=t(function(t,e){c(t,l,n,"_i"),t._i=i(null),t._f=void 0,t._l=void 0,t[d]=0,void 0!=e&&a(e,r,t[s],t)});return o(l.prototype,{clear:function(){for(var t=this,n=t._i,r=t._f;r;r=r.n)r.r=!0,r.p&&(r.p=r.p.n=void 0),delete n[r.i];t._f=t._l=void 0,t[d]=0},delete:function(t){var n=this,r=y(n,t);if(r){var e=r.n,i=r.p;delete n._i[r.i],r.r=!0,i&&(i.n=e),e&&(e.p=i),n._f==r&&(n._f=e),n._l==r&&(n._l=i),n[d]--}return!!r},forEach:function(t){c(this,l,"forEach");for(var n,r=u(t,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(r(n.v,n.k,this);n&&n.r;)n=n.p},has:function(t){return!!y(this,t)}}),v&&e(l.prototype,"size",{get:function(){return f(this[d])}}),l},def:function(t,n,r){var e,i,o=y(t,n);return o?o.v=r:(t._l=o={i:i=p(n,!0),k:n,v:r,p:e=t._l,n:void 0,r:!1},t._f||(t._f=o),e&&(e.n=o),t[d]++,"F"!==i&&(t._i[i]=o)),t},getEntry:y,setStrong:function(t,n,r){s(t,n,function(t,n){this._t=t,this._k=n,this._l=void 0},function(){for(var t=this,n=t._k,r=t._l;r&&r.r;)r=r.p;return t._t&&(t._l=r=r?r.n:t._t._f)?"keys"==n?l(0,r.k):"values"==n?l(0,r.v):l(0,[r.k,r.v]):(t._t=void 0,l(1))},r?"entries":"values",!r,!0),h(n)}}},function(t,n,r){var e=r(114),i=r(161);t.exports=function(t){return function(){if(e(this)!=t)throw TypeError(t+"#toJSON isn't generic");return i(this)}}},function(t,n,r){"use strict";var e=r(73),i=r(65).getWeak,o=r(2),u=r(6),c=r(68),f=r(79),a=r(48),s=r(24),l=a(5),h=a(6),v=0,p=function(t){return t._l||(t._l=new d)},d=function(){this.a=[]},y=function(t,n){return l(t.a,function(t){return t[0]===n})};d.prototype={get:function(t){var n=y(this,t);if(n)return n[1]},has:function(t){return!!y(this,t)},set:function(t,n){var r=y(this,t);r?r[1]=n:this.a.push([t,n])},delete:function(t){var n=h(this.a,function(n){return n[0]===t});return~n&&this.a.splice(n,1),!!~n}},t.exports={getConstructor:function(t,n,r,o){var a=t(function(t,e){c(t,a,n,"_i"),t._i=v++,t._l=void 0,void 0!=e&&f(e,r,t[o],t)});return e(a.prototype,{delete:function(t){if(!u(t))return!1;var n=i(t);return!0===n?p(this).delete(t):n&&s(n,this._i)&&delete n[this._i]},has:function(t){if(!u(t))return!1;var n=i(t);return!0===n?p(this).has(t):n&&s(n,this._i)}}),a},def:function(t,n,r){var e=i(o(n),!0);return!0===e?p(t).set(n,r):e[t._i]=r,t},ufstore:p}},function(t,n,r){t.exports=!r(10)&&!r(4)(function(){return 7!=Object.defineProperty(r(132)("div"),"a",{get:function(){return 7}}).a})},function(t,n,r){var e=r(6),i=Math.floor;t.exports=function(t){return!e(t)&&isFinite(t)&&i(t)===t}},function(t,n,r){var e=r(2);t.exports=function(t,n,r,i){try{return i?n(e(r)[0],r[1]):n(r)}catch(n){var o=t.return;throw void 0!==o&&e(o.call(t)),n}}},function(t,n){t.exports=function(t,n){return{value:n,done:!!t}}},function(t,n){t.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&t<1e-8?t-t*t/2:Math.log(1+t)}},function(t,n,r){"use strict";var e=r(72),i=r(125),o=r(116),u=r(17),c=r(115),f=Object.assign;t.exports=!f||r(4)(function(){var t={},n={},r=Symbol(),e="abcdefghijklmnopqrst";return t[r]=7,e.split("").forEach(function(t){n[t]=t}),7!=f({},t)[r]||Object.keys(f({},n)).join("")!=e})?function(t,n){for(var r=u(t),f=arguments.length,a=1,s=i.f,l=o.f;f>a;)for(var h,v=c(arguments[a++]),p=s?e(v).concat(s(v)):e(v),d=p.length,y=0;d>y;)l.call(v,h=p[y++])&&(r[h]=v[h]);return r}:f},function(t,n,r){var e=r(11),i=r(2),o=r(72);t.exports=r(10)?Object.defineProperties:function(t,n){i(t);for(var r,u=o(n),c=u.length,f=0;c>f;)e.f(t,r=u[f++],n[r]);return t}},function(t,n,r){var e=r(30),i=r(71).f,o={}.toString,u="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],c=function(t){try{return i(t)}catch(t){return u.slice()}};t.exports.f=function(t){return u&&"[object Window]"==o.call(t)?c(t):i(e(t))}},function(t,n,r){var e=r(24),i=r(30),o=r(117)(!1),u=r(145)("IE_PROTO");t.exports=function(t,n){var r,c=i(t),f=0,a=[];for(r in c)r!=u&&e(c,r)&&a.push(r);for(;n.length>f;)e(c,r=n[f++])&&(~o(a,r)||a.push(r));return a}},function(t,n,r){var e=r(72),i=r(30),o=r(116).f;t.exports=function(t){return function(n){for(var r,u=i(n),c=e(u),f=c.length,a=0,s=[];f>a;)o.call(u,r=c[a++])&&s.push(t?[r,u[r]]:u[r]);return s}}},function(t,n,r){var e=r(71),i=r(125),o=r(2),u=r(3).Reflect;t.exports=u&&u.ownKeys||function(t){var n=e.f(o(t)),r=i.f;return r?n.concat(r(t)):n}},function(t,n,r){var e=r(3).parseFloat,i=r(82).trim;t.exports=1/e(r(150)+"-0")!=-1/0?function(t){var n=i(String(t),3),r=e(n);return 0===r&&"-"==n.charAt(0)?-0:r}:e},function(t,n,r){var e=r(3).parseInt,i=r(82).trim,o=r(150),u=/^[\-+]?0[xX]/;t.exports=8!==e(o+"08")||22!==e(o+"0x16")?function(t,n){var r=i(String(t),3);return e(r,n>>>0||(u.test(r)?16:10))}:e},function(t,n){t.exports=Object.is||function(t,n){return t===n?0!==t||1/t==1/n:t!=t&&n!=n}},function(t,n,r){var e=r(16),i=r(149),o=r(46);t.exports=function(t,n,r,u){var c=String(o(t)),f=c.length,a=void 0===r?" ":String(r),s=e(n);if(s<=f||""==a)return c;var l=s-f,h=i.call(a,Math.ceil(l/a.length));return h.length>l&&(h=h.slice(0,l)),u?h+c:c+h}},function(t,n,r){n.f=r(7)},function(t,n,r){"use strict";var e=r(164);t.exports=r(118)("Map",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{get:function(t){var n=e.getEntry(this,t);return n&&n.v},set:function(t,n){return e.def(this,0===t?0:t,n)}},e,!0)},function(t,n,r){r(10)&&"g"!=/./g.flags&&r(11).f(RegExp.prototype,"flags",{configurable:!0,get:r(120)})},function(t,n,r){"use strict";var e=r(164);t.exports=r(118)("Set",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return e.def(this,t=0===t?0:t,t)}},e)},function(t,n,r){"use strict";var e,i=r(48)(0),o=r(28),u=r(65),c=r(172),f=r(166),a=r(6),s=u.getWeak,l=Object.isExtensible,h=f.ufstore,v={},p=function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},d={get:function(t){if(a(t)){var n=s(t);return!0===n?h(this).get(t):n?n[this._i]:void 0}},set:function(t,n){return f.def(this,t,n)}},y=t.exports=r(118)("WeakMap",p,d,f,!0,!0);7!=(new y).set((Object.freeze||Object)(v),7).get(v)&&(e=f.getConstructor(p),c(e.prototype,d),u.NEED=!0,i(["delete","has","get","set"],function(t){var n=y.prototype,r=n[t];o(n,t,function(n,i){if(a(n)&&!l(n)){this._f||(this._f=new e);var o=this._f[t](n,i);return"set"==t?this:o}return r.call(this,n,i)})}))},,,,function(t,n){"use strict";function r(){var t=document.querySelector("#page-nav");if(t&&!document.querySelector("#page-nav .extend.prev")&&(t.innerHTML='<a class="extend prev disabled" rel="prev">&laquo; Prev</a>'+t.innerHTML),t&&!document.querySelector("#page-nav .extend.next")&&(t.innerHTML=t.innerHTML+'<a class="extend next disabled" rel="next">Next &raquo;</a>'),yiliaConfig&&yiliaConfig.open_in_new){document.querySelectorAll(".article-entry a:not(.article-more-a)").forEach(function(t){var n=t.getAttribute("target");n&&""!==n||t.setAttribute("target","_blank")})}if(yiliaConfig&&yiliaConfig.toc_hide_index){document.querySelectorAll(".toc-number").forEach(function(t){t.style.display="none"})}var n=document.querySelector("#js-aboutme");n&&0!==n.length&&(n.innerHTML=n.innerText)}t.exports={init:r}},function(t,n,r){"use strict";function e(t){return t&&t.__esModule?t:{default:t}}function i(t,n){var r=/\/|index.html/g;return t.replace(r,"")===n.replace(r,"")}function o(){for(var t=document.querySelectorAll(".js-header-menu li a"),n=window.location.pathname,r=0,e=t.length;r<e;r++){var o=t[r];i(n,o.getAttribute("href"))&&(0,h.default)(o,"active")}}function u(t){for(var n=t.offsetLeft,r=t.offsetParent;null!==r;)n+=r.offsetLeft,r=r.offsetParent;return n}function c(t){for(var n=t.offsetTop,r=t.offsetParent;null!==r;)n+=r.offsetTop,r=r.offsetParent;return n}function f(t,n,r,e,i){var o=u(t),f=c(t)-n;if(f-r<=i){var a=t.$newDom;a||(a=t.cloneNode(!0),(0,d.default)(t,a),t.$newDom=a,a.style.position="fixed",a.style.top=(r||f)+"px",a.style.left=o+"px",a.style.zIndex=e||2,a.style.width="100%",a.style.color="#fff"),a.style.visibility="visible",t.style.visibility="hidden"}else{t.style.visibility="visible";var s=t.$newDom;s&&(s.style.visibility="hidden")}}function a(){var t=document.querySelector(".js-overlay"),n=document.querySelector(".js-header-menu");f(t,document.body.scrollTop,-63,2,0),f(n,document.body.scrollTop,1,3,0)}function s(){document.querySelector("#container").addEventListener("scroll",function(t){a()}),window.addEventListener("scroll",function(t){a()}),a()}var l=r(156),h=e(l),v=r(157),p=(e(v),r(382)),d=e(p),y=r(128),g=e(y),b=r(190),m=e(b),x=r(129);(function(){g.default.versions.mobile&&window.screen.width<800&&(o(),s())})(),(0,x.addLoadEvent)(function(){m.default.init()}),t.exports={}},,,,function(t,n,r){(function(t){"use strict";function n(t,n,r){t[n]||Object[e](t,n,{writable:!0,configurable:!0,value:r})}if(r(381),r(391),r(198),t._babelPolyfill)throw new Error("only one instance of babel-polyfill is allowed");t._babelPolyfill=!0;var e="defineProperty";n(String.prototype,"padLeft","".padStart),n(String.prototype,"padRight","".padEnd),"pop,reverse,shift,keys,values,entries,indexOf,every,some,forEach,map,filter,find,findIndex,includes,join,slice,concat,push,splice,unshift,sort,lastIndexOf,reduce,reduceRight,copyWithin,fill".split(",").forEach(function(t){[][t]&&n(Array,t,Function.call.bind([][t]))})}).call(n,function(){return this}())},,,function(t,n,r){r(210),t.exports=r(52).RegExp.escape},,,,function(t,n,r){var e=r(6),i=r(138),o=r(7)("species");t.exports=function(t){var n;return i(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!i(n.prototype)||(n=void 0),e(n)&&null===(n=n[o])&&(n=void 0)),void 0===n?Array:n}},function(t,n,r){var e=r(202);t.exports=function(t,n){return new(e(t))(n)}},function(t,n,r){"use strict";var e=r(2),i=r(50),o="number";t.exports=function(t){if("string"!==t&&t!==o&&"default"!==t)throw TypeError("Incorrect hint");return i(e(this),t!=o)}},function(t,n,r){var e=r(72),i=r(125),o=r(116);t.exports=function(t){var n=e(t),r=i.f;if(r)for(var u,c=r(t),f=o.f,a=0;c.length>a;)f.call(t,u=c[a++])&&n.push(u);return n}},function(t,n,r){var e=r(72),i=r(30);t.exports=function(t,n){for(var r,o=i(t),u=e(o),c=u.length,f=0;c>f;)if(o[r=u[f++]]===n)return r}},function(t,n,r){"use strict";var e=r(208),i=r(121),o=r(26);t.exports=function(){for(var t=o(this),n=arguments.length,r=Array(n),u=0,c=e._,f=!1;n>u;)(r[u]=arguments[u++])===c&&(f=!0);return function(){var e,o=this,u=arguments.length,a=0,s=0;if(!f&&!u)return i(t,r,o);if(e=r.slice(),f)for(;n>a;a++)e[a]===c&&(e[a]=arguments[s++]);for(;u>s;)e.push(arguments[s++]);return i(t,e,o)}}},function(t,n,r){t.exports=r(3)},function(t,n){t.exports=function(t,n){var r=n===Object(n)?function(t){return n[t]}:n;return function(n){return String(n).replace(t,r)}}},function(t,n,r){var e=r(1),i=r(209)(/[\\^$*+?.()|[\]{}]/g,"\\$&");e(e.S,"RegExp",{escape:function(t){return i(t)}})},function(t,n,r){var e=r(1);e(e.P,"Array",{copyWithin:r(160)}),r(78)("copyWithin")},function(t,n,r){"use strict";var e=r(1),i=r(48)(4);e(e.P+e.F*!r(47)([].every,!0),"Array",{every:function(t){return i(this,t,arguments[1])}})},function(t,n,r){var e=r(1);e(e.P,"Array",{fill:r(130)}),r(78)("fill")},function(t,n,r){"use strict";var e=r(1),i=r(48)(2);e(e.P+e.F*!r(47)([].filter,!0),"Array",{filter:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(1),i=r(48)(6),o="findIndex",u=!0;o in[]&&Array(1)[o](function(){u=!1}),e(e.P+e.F*u,"Array",{findIndex:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r(78)(o)},function(t,n,r){"use strict";var e=r(1),i=r(48)(5),o="find",u=!0;o in[]&&Array(1)[o](function(){u=!1}),e(e.P+e.F*u,"Array",{find:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r(78)(o)},function(t,n,r){"use strict";var e=r(1),i=r(48)(0),o=r(47)([].forEach,!0);e(e.P+e.F*!o,"Array",{forEach:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(53),i=r(1),o=r(17),u=r(169),c=r(137),f=r(16),a=r(131),s=r(154);i(i.S+i.F*!r(123)(function(t){Array.from(t)}),"Array",{from:function(t){var n,r,i,l,h=o(t),v="function"==typeof this?this:Array,p=arguments.length,d=p>1?arguments[1]:void 0,y=void 0!==d,g=0,b=s(h);if(y&&(d=e(d,p>2?arguments[2]:void 0,2)),void 0==b||v==Array&&c(b))for(n=f(h.length),r=new v(n);n>g;g++)a(r,g,y?d(h[g],g):h[g]);else for(l=b.call(h),r=new v;!(i=l.next()).done;g++)a(r,g,y?u(l,d,[i.value,g],!0):i.value);return r.length=g,r}})},function(t,n,r){"use strict";var e=r(1),i=r(117)(!1),o=[].indexOf,u=!!o&&1/[1].indexOf(1,-0)<0;e(e.P+e.F*(u||!r(47)(o)),"Array",{indexOf:function(t){return u?o.apply(this,arguments)||0:i(this,t,arguments[1])}})},function(t,n,r){var e=r(1);e(e.S,"Array",{isArray:r(138)})},function(t,n,r){"use strict";var e=r(1),i=r(30),o=[].join;e(e.P+e.F*(r(115)!=Object||!r(47)(o)),"Array",{join:function(t){return o.call(i(this),void 0===t?",":t)}})},function(t,n,r){"use strict";var e=r(1),i=r(30),o=r(67),u=r(16),c=[].lastIndexOf,f=!!c&&1/[1].lastIndexOf(1,-0)<0;e(e.P+e.F*(f||!r(47)(c)),"Array",{lastIndexOf:function(t){if(f)return c.apply(this,arguments)||0;var n=i(this),r=u(n.length),e=r-1;for(arguments.length>1&&(e=Math.min(e,o(arguments[1]))),e<0&&(e=r+e);e>=0;e--)if(e in n&&n[e]===t)return e||0;return-1}})},function(t,n,r){"use strict";var e=r(1),i=r(48)(1);e(e.P+e.F*!r(47)([].map,!0),"Array",{map:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(1),i=r(131);e(e.S+e.F*r(4)(function(){function t(){}return!(Array.of.call(t)instanceof t)}),"Array",{of:function(){for(var t=0,n=arguments.length,r=new("function"==typeof this?this:Array)(n);n>t;)i(r,t,arguments[t++]);return r.length=n,r}})},function(t,n,r){"use strict";var e=r(1),i=r(162);e(e.P+e.F*!r(47)([].reduceRight,!0),"Array",{reduceRight:function(t){return i(this,t,arguments.length,arguments[1],!0)}})},function(t,n,r){"use strict";var e=r(1),i=r(162);e(e.P+e.F*!r(47)([].reduce,!0),"Array",{reduce:function(t){return i(this,t,arguments.length,arguments[1],!1)}})},function(t,n,r){"use strict";var e=r(1),i=r(135),o=r(45),u=r(75),c=r(16),f=[].slice;e(e.P+e.F*r(4)(function(){i&&f.call(i)}),"Array",{slice:function(t,n){var r=c(this.length),e=o(this);if(n=void 0===n?r:n,"Array"==e)return f.call(this,t,n);for(var i=u(t,r),a=u(n,r),s=c(a-i),l=Array(s),h=0;h<s;h++)l[h]="String"==e?this.charAt(i+h):this[i+h];return l}})},function(t,n,r){"use strict";var e=r(1),i=r(48)(3);e(e.P+e.F*!r(47)([].some,!0),"Array",{some:function(t){return i(this,t,arguments[1])}})},function(t,n,r){"use strict";var e=r(1),i=r(26),o=r(17),u=r(4),c=[].sort,f=[1,2,3];e(e.P+e.F*(u(function(){f.sort(void 0)})||!u(function(){f.sort(null)})||!r(47)(c)),"Array",{sort:function(t){return void 0===t?c.call(o(this)):c.call(o(this),i(t))}})},function(t,n,r){r(74)("Array")},function(t,n,r){var e=r(1);e(e.S,"Date",{now:function(){return(new Date).getTime()}})},function(t,n,r){"use strict";var e=r(1),i=r(4),o=Date.prototype.getTime,u=function(t){return t>9?t:"0"+t};e(e.P+e.F*(i(function(){return"0385-07-25T07:06:39.999Z"!=new Date(-5e13-1).toISOString()})||!i(function(){new Date(NaN).toISOString()})),"Date",{toISOString:function(){
if(!isFinite(o.call(this)))throw RangeError("Invalid time value");var t=this,n=t.getUTCFullYear(),r=t.getUTCMilliseconds(),e=n<0?"-":n>9999?"+":"";return e+("00000"+Math.abs(n)).slice(e?-6:-4)+"-"+u(t.getUTCMonth()+1)+"-"+u(t.getUTCDate())+"T"+u(t.getUTCHours())+":"+u(t.getUTCMinutes())+":"+u(t.getUTCSeconds())+"."+(r>99?r:"0"+u(r))+"Z"}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(50);e(e.P+e.F*r(4)(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}),"Date",{toJSON:function(t){var n=i(this),r=o(n);return"number"!=typeof r||isFinite(r)?n.toISOString():null}})},function(t,n,r){var e=r(7)("toPrimitive"),i=Date.prototype;e in i||r(27)(i,e,r(204))},function(t,n,r){var e=Date.prototype,i="Invalid Date",o="toString",u=e[o],c=e.getTime;new Date(NaN)+""!=i&&r(28)(e,o,function(){var t=c.call(this);return t===t?u.call(this):i})},function(t,n,r){var e=r(1);e(e.P,"Function",{bind:r(163)})},function(t,n,r){"use strict";var e=r(6),i=r(32),o=r(7)("hasInstance"),u=Function.prototype;o in u||r(11).f(u,o,{value:function(t){if("function"!=typeof this||!e(t))return!1;if(!e(this.prototype))return t instanceof this;for(;t=i(t);)if(this.prototype===t)return!0;return!1}})},function(t,n,r){var e=r(11).f,i=r(66),o=r(24),u=Function.prototype,c="name",f=Object.isExtensible||function(){return!0};c in u||r(10)&&e(u,c,{configurable:!0,get:function(){try{var t=this,n=(""+t).match(/^\s*function ([^ (]*)/)[1];return o(t,c)||!f(t)||e(t,c,i(5,n)),n}catch(t){return""}}})},function(t,n,r){var e=r(1),i=r(171),o=Math.sqrt,u=Math.acosh;e(e.S+e.F*!(u&&710==Math.floor(u(Number.MAX_VALUE))&&u(1/0)==1/0),"Math",{acosh:function(t){return(t=+t)<1?NaN:t>94906265.62425156?Math.log(t)+Math.LN2:i(t-1+o(t-1)*o(t+1))}})},function(t,n,r){function e(t){return isFinite(t=+t)&&0!=t?t<0?-e(-t):Math.log(t+Math.sqrt(t*t+1)):t}var i=r(1),o=Math.asinh;i(i.S+i.F*!(o&&1/o(0)>0),"Math",{asinh:e})},function(t,n,r){var e=r(1),i=Math.atanh;e(e.S+e.F*!(i&&1/i(-0)<0),"Math",{atanh:function(t){return 0==(t=+t)?t:Math.log((1+t)/(1-t))/2}})},function(t,n,r){var e=r(1),i=r(142);e(e.S,"Math",{cbrt:function(t){return i(t=+t)*Math.pow(Math.abs(t),1/3)}})},function(t,n,r){var e=r(1);e(e.S,"Math",{clz32:function(t){return(t>>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},function(t,n,r){var e=r(1),i=Math.exp;e(e.S,"Math",{cosh:function(t){return(i(t=+t)+i(-t))/2}})},function(t,n,r){var e=r(1),i=r(141);e(e.S+e.F*(i!=Math.expm1),"Math",{expm1:i})},function(t,n,r){var e=r(1),i=r(142),o=Math.pow,u=o(2,-52),c=o(2,-23),f=o(2,127)*(2-c),a=o(2,-126),s=function(t){return t+1/u-1/u};e(e.S,"Math",{fround:function(t){var n,r,e=Math.abs(t),o=i(t);return e<a?o*s(e/a/c)*a*c:(n=(1+c/u)*e,r=n-(n-e),r>f||r!=r?o*(1/0):o*r)}})},function(t,n,r){var e=r(1),i=Math.abs;e(e.S,"Math",{hypot:function(t,n){for(var r,e,o=0,u=0,c=arguments.length,f=0;u<c;)r=i(arguments[u++]),f<r?(e=f/r,o=o*e*e+1,f=r):r>0?(e=r/f,o+=e*e):o+=r;return f===1/0?1/0:f*Math.sqrt(o)}})},function(t,n,r){var e=r(1),i=Math.imul;e(e.S+e.F*r(4)(function(){return-5!=i(4294967295,5)||2!=i.length}),"Math",{imul:function(t,n){var r=65535,e=+t,i=+n,o=r&e,u=r&i;return 0|o*u+((r&e>>>16)*u+o*(r&i>>>16)<<16>>>0)}})},function(t,n,r){var e=r(1);e(e.S,"Math",{log10:function(t){return Math.log(t)/Math.LN10}})},function(t,n,r){var e=r(1);e(e.S,"Math",{log1p:r(171)})},function(t,n,r){var e=r(1);e(e.S,"Math",{log2:function(t){return Math.log(t)/Math.LN2}})},function(t,n,r){var e=r(1);e(e.S,"Math",{sign:r(142)})},function(t,n,r){var e=r(1),i=r(141),o=Math.exp;e(e.S+e.F*r(4)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(t){return Math.abs(t=+t)<1?(i(t)-i(-t))/2:(o(t-1)-o(-t-1))*(Math.E/2)}})},function(t,n,r){var e=r(1),i=r(141),o=Math.exp;e(e.S,"Math",{tanh:function(t){var n=i(t=+t),r=i(-t);return n==1/0?1:r==1/0?-1:(n-r)/(o(t)+o(-t))}})},function(t,n,r){var e=r(1);e(e.S,"Math",{trunc:function(t){return(t>0?Math.floor:Math.ceil)(t)}})},function(t,n,r){"use strict";var e=r(3),i=r(24),o=r(45),u=r(136),c=r(50),f=r(4),a=r(71).f,s=r(31).f,l=r(11).f,h=r(82).trim,v="Number",p=e[v],d=p,y=p.prototype,g=o(r(70)(y))==v,b="trim"in String.prototype,m=function(t){var n=c(t,!1);if("string"==typeof n&&n.length>2){n=b?n.trim():h(n,3);var r,e,i,o=n.charCodeAt(0);if(43===o||45===o){if(88===(r=n.charCodeAt(2))||120===r)return NaN}else if(48===o){switch(n.charCodeAt(1)){case 66:case 98:e=2,i=49;break;case 79:case 111:e=8,i=55;break;default:return+n}for(var u,f=n.slice(2),a=0,s=f.length;a<s;a++)if((u=f.charCodeAt(a))<48||u>i)return NaN;return parseInt(f,e)}}return+n};if(!p(" 0o1")||!p("0b1")||p("+0x1")){p=function(t){var n=arguments.length<1?0:t,r=this;return r instanceof p&&(g?f(function(){y.valueOf.call(r)}):o(r)!=v)?u(new d(m(n)),r,p):m(n)};for(var x,w=r(10)?a(d):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),S=0;w.length>S;S++)i(d,x=w[S])&&!i(p,x)&&l(p,x,s(d,x));p.prototype=y,y.constructor=p,r(28)(e,v,p)}},function(t,n,r){var e=r(1);e(e.S,"Number",{EPSILON:Math.pow(2,-52)})},function(t,n,r){var e=r(1),i=r(3).isFinite;e(e.S,"Number",{isFinite:function(t){return"number"==typeof t&&i(t)}})},function(t,n,r){var e=r(1);e(e.S,"Number",{isInteger:r(168)})},function(t,n,r){var e=r(1);e(e.S,"Number",{isNaN:function(t){return t!=t}})},function(t,n,r){var e=r(1),i=r(168),o=Math.abs;e(e.S,"Number",{isSafeInteger:function(t){return i(t)&&o(t)<=9007199254740991}})},function(t,n,r){var e=r(1);e(e.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},function(t,n,r){var e=r(1);e(e.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},function(t,n,r){var e=r(1),i=r(178);e(e.S+e.F*(Number.parseFloat!=i),"Number",{parseFloat:i})},function(t,n,r){var e=r(1),i=r(179);e(e.S+e.F*(Number.parseInt!=i),"Number",{parseInt:i})},function(t,n,r){"use strict";var e=r(1),i=r(67),o=r(159),u=r(149),c=1..toFixed,f=Math.floor,a=[0,0,0,0,0,0],s="Number.toFixed: incorrect invocation!",l="0",h=function(t,n){for(var r=-1,e=n;++r<6;)e+=t*a[r],a[r]=e%1e7,e=f(e/1e7)},v=function(t){for(var n=6,r=0;--n>=0;)r+=a[n],a[n]=f(r/t),r=r%t*1e7},p=function(){for(var t=6,n="";--t>=0;)if(""!==n||0===t||0!==a[t]){var r=String(a[t]);n=""===n?r:n+u.call(l,7-r.length)+r}return n},d=function(t,n,r){return 0===n?r:n%2==1?d(t,n-1,r*t):d(t*t,n/2,r)},y=function(t){for(var n=0,r=t;r>=4096;)n+=12,r/=4096;for(;r>=2;)n+=1,r/=2;return n};e(e.P+e.F*(!!c&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!r(4)(function(){c.call({})})),"Number",{toFixed:function(t){var n,r,e,c,f=o(this,s),a=i(t),g="",b=l;if(a<0||a>20)throw RangeError(s);if(f!=f)return"NaN";if(f<=-1e21||f>=1e21)return String(f);if(f<0&&(g="-",f=-f),f>1e-21)if(n=y(f*d(2,69,1))-69,r=n<0?f*d(2,-n,1):f/d(2,n,1),r*=4503599627370496,(n=52-n)>0){for(h(0,r),e=a;e>=7;)h(1e7,0),e-=7;for(h(d(10,e,1),0),e=n-1;e>=23;)v(1<<23),e-=23;v(1<<e),h(1,1),v(2),b=p()}else h(0,r),h(1<<-n,0),b=p()+u.call(l,a);return a>0?(c=b.length,b=g+(c<=a?"0."+u.call(l,a-c)+b:b.slice(0,c-a)+"."+b.slice(c-a))):b=g+b,b}})},function(t,n,r){"use strict";var e=r(1),i=r(4),o=r(159),u=1..toPrecision;e(e.P+e.F*(i(function(){return"1"!==u.call(1,void 0)})||!i(function(){u.call({})})),"Number",{toPrecision:function(t){var n=o(this,"Number#toPrecision: incorrect invocation!");return void 0===t?u.call(n):u.call(n,t)}})},function(t,n,r){var e=r(1);e(e.S+e.F,"Object",{assign:r(172)})},function(t,n,r){var e=r(1);e(e.S,"Object",{create:r(70)})},function(t,n,r){var e=r(1);e(e.S+e.F*!r(10),"Object",{defineProperties:r(173)})},function(t,n,r){var e=r(1);e(e.S+e.F*!r(10),"Object",{defineProperty:r(11).f})},function(t,n,r){var e=r(6),i=r(65).onFreeze;r(49)("freeze",function(t){return function(n){return t&&e(n)?t(i(n)):n}})},function(t,n,r){var e=r(30),i=r(31).f;r(49)("getOwnPropertyDescriptor",function(){return function(t,n){return i(e(t),n)}})},function(t,n,r){r(49)("getOwnPropertyNames",function(){return r(174).f})},function(t,n,r){var e=r(17),i=r(32);r(49)("getPrototypeOf",function(){return function(t){return i(e(t))}})},function(t,n,r){var e=r(6);r(49)("isExtensible",function(t){return function(n){return!!e(n)&&(!t||t(n))}})},function(t,n,r){var e=r(6);r(49)("isFrozen",function(t){return function(n){return!e(n)||!!t&&t(n)}})},function(t,n,r){var e=r(6);r(49)("isSealed",function(t){return function(n){return!e(n)||!!t&&t(n)}})},function(t,n,r){var e=r(1);e(e.S,"Object",{is:r(180)})},function(t,n,r){var e=r(17),i=r(72);r(49)("keys",function(){return function(t){return i(e(t))}})},function(t,n,r){var e=r(6),i=r(65).onFreeze;r(49)("preventExtensions",function(t){return function(n){return t&&e(n)?t(i(n)):n}})},function(t,n,r){var e=r(6),i=r(65).onFreeze;r(49)("seal",function(t){return function(n){return t&&e(n)?t(i(n)):n}})},function(t,n,r){var e=r(1);e(e.S,"Object",{setPrototypeOf:r(144).set})},function(t,n,r){"use strict";var e=r(114),i={};i[r(7)("toStringTag")]="z",i+""!="[object z]"&&r(28)(Object.prototype,"toString",function(){return"[object "+e(this)+"]"},!0)},function(t,n,r){var e=r(1),i=r(178);e(e.G+e.F*(parseFloat!=i),{parseFloat:i})},function(t,n,r){var e=r(1),i=r(179);e(e.G+e.F*(parseInt!=i),{parseInt:i})},function(t,n,r){"use strict";var e,i,o,u=r(69),c=r(3),f=r(53),a=r(114),s=r(1),l=r(6),h=r(26),v=r(68),p=r(79),d=r(146),y=r(151).set,g=r(143)(),b="Promise",m=c.TypeError,x=c.process,w=c[b],x=c.process,S="process"==a(x),_=function(){},O=!!function(){try{var t=w.resolve(1),n=(t.constructor={})[r(7)("species")]=function(t){t(_,_)};return(S||"function"==typeof PromiseRejectionEvent)&&t.then(_)instanceof n}catch(t){}}(),E=function(t,n){return t===n||t===w&&n===o},P=function(t){var n;return!(!l(t)||"function"!=typeof(n=t.then))&&n},j=function(t){return E(w,t)?new F(t):new i(t)},F=i=function(t){var n,r;this.promise=new t(function(t,e){if(void 0!==n||void 0!==r)throw m("Bad Promise constructor");n=t,r=e}),this.resolve=h(n),this.reject=h(r)},M=function(t){try{t()}catch(t){return{error:t}}},A=function(t,n){if(!t._n){t._n=!0;var r=t._c;g(function(){for(var e=t._v,i=1==t._s,o=0;r.length>o;)!function(n){var r,o,u=i?n.ok:n.fail,c=n.resolve,f=n.reject,a=n.domain;try{u?(i||(2==t._h&&I(t),t._h=1),!0===u?r=e:(a&&a.enter(),r=u(e),a&&a.exit()),r===n.promise?f(m("Promise-chain cycle")):(o=P(r))?o.call(r,c,f):c(r)):f(e)}catch(t){f(t)}}(r[o++]);t._c=[],t._n=!1,n&&!t._h&&N(t)})}},N=function(t){y.call(c,function(){var n,r,e,i=t._v;if(T(t)&&(n=M(function(){S?x.emit("unhandledRejection",i,t):(r=c.onunhandledrejection)?r({promise:t,reason:i}):(e=c.console)&&e.error&&e.error("Unhandled promise rejection",i)}),t._h=S||T(t)?2:1),t._a=void 0,n)throw n.error})},T=function(t){if(1==t._h)return!1;for(var n,r=t._a||t._c,e=0;r.length>e;)if(n=r[e++],n.fail||!T(n.promise))return!1;return!0},I=function(t){y.call(c,function(){var n;S?x.emit("rejectionHandled",t):(n=c.onrejectionhandled)&&n({promise:t,reason:t._v})})},k=function(t){var n=this;n._d||(n._d=!0,n=n._w||n,n._v=t,n._s=2,n._a||(n._a=n._c.slice()),A(n,!0))},L=function(t){var n,r=this;if(!r._d){r._d=!0,r=r._w||r;try{if(r===t)throw m("Promise can't be resolved itself");(n=P(t))?g(function(){var e={_w:r,_d:!1};try{n.call(t,f(L,e,1),f(k,e,1))}catch(t){k.call(e,t)}}):(r._v=t,r._s=1,A(r,!1))}catch(t){k.call({_w:r,_d:!1},t)}}};O||(w=function(t){v(this,w,b,"_h"),h(t),e.call(this);try{t(f(L,this,1),f(k,this,1))}catch(t){k.call(this,t)}},e=function(t){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1},e.prototype=r(73)(w.prototype,{then:function(t,n){var r=j(d(this,w));return r.ok="function"!=typeof t||t,r.fail="function"==typeof n&&n,r.domain=S?x.domain:void 0,this._c.push(r),this._a&&this._a.push(r),this._s&&A(this,!1),r.promise},catch:function(t){return this.then(void 0,t)}}),F=function(){var t=new e;this.promise=t,this.resolve=f(L,t,1),this.reject=f(k,t,1)}),s(s.G+s.W+s.F*!O,{Promise:w}),r(81)(w,b),r(74)(b),o=r(52)[b],s(s.S+s.F*!O,b,{reject:function(t){var n=j(this);return(0,n.reject)(t),n.promise}}),s(s.S+s.F*(u||!O),b,{resolve:function(t){if(t instanceof w&&E(t.constructor,this))return t;var n=j(this);return(0,n.resolve)(t),n.promise}}),s(s.S+s.F*!(O&&r(123)(function(t){w.all(t).catch(_)})),b,{all:function(t){var n=this,r=j(n),e=r.resolve,i=r.reject,o=M(function(){var r=[],o=0,u=1;p(t,!1,function(t){var c=o++,f=!1;r.push(void 0),u++,n.resolve(t).then(function(t){f||(f=!0,r[c]=t,--u||e(r))},i)}),--u||e(r)});return o&&i(o.error),r.promise},race:function(t){var n=this,r=j(n),e=r.reject,i=M(function(){p(t,!1,function(t){n.resolve(t).then(r.resolve,e)})});return i&&e(i.error),r.promise}})},function(t,n,r){var e=r(1),i=r(26),o=r(2),u=(r(3).Reflect||{}).apply,c=Function.apply;e(e.S+e.F*!r(4)(function(){u(function(){})}),"Reflect",{apply:function(t,n,r){var e=i(t),f=o(r);return u?u(e,n,f):c.call(e,n,f)}})},function(t,n,r){var e=r(1),i=r(70),o=r(26),u=r(2),c=r(6),f=r(4),a=r(163),s=(r(3).Reflect||{}).construct,l=f(function(){function t(){}return!(s(function(){},[],t)instanceof t)}),h=!f(function(){s(function(){})});e(e.S+e.F*(l||h),"Reflect",{construct:function(t,n){o(t),u(n);var r=arguments.length<3?t:o(arguments[2]);if(h&&!l)return s(t,n,r);if(t==r){switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3])}var e=[null];return e.push.apply(e,n),new(a.apply(t,e))}var f=r.prototype,v=i(c(f)?f:Object.prototype),p=Function.apply.call(t,v,n);return c(p)?p:v}})},function(t,n,r){var e=r(11),i=r(1),o=r(2),u=r(50);i(i.S+i.F*r(4)(function(){Reflect.defineProperty(e.f({},1,{value:1}),1,{value:2})}),"Reflect",{defineProperty:function(t,n,r){o(t),n=u(n,!0),o(r);try{return e.f(t,n,r),!0}catch(t){return!1}}})},function(t,n,r){var e=r(1),i=r(31).f,o=r(2);e(e.S,"Reflect",{deleteProperty:function(t,n){var r=i(o(t),n);return!(r&&!r.configurable)&&delete t[n]}})},function(t,n,r){"use strict";var e=r(1),i=r(2),o=function(t){this._t=i(t),this._i=0;var n,r=this._k=[];for(n in t)r.push(n)};r(139)(o,"Object",function(){var t,n=this,r=n._k;do{if(n._i>=r.length)return{value:void 0,done:!0}}while(!((t=r[n._i++])in n._t));return{value:t,done:!1}}),e(e.S,"Reflect",{enumerate:function(t){return new o(t)}})},function(t,n,r){var e=r(31),i=r(1),o=r(2);i(i.S,"Reflect",{getOwnPropertyDescriptor:function(t,n){return e.f(o(t),n)}})},function(t,n,r){var e=r(1),i=r(32),o=r(2);e(e.S,"Reflect",{getPrototypeOf:function(t){return i(o(t))}})},function(t,n,r){function e(t,n){var r,c,s=arguments.length<3?t:arguments[2];return a(t)===s?t[n]:(r=i.f(t,n))?u(r,"value")?r.value:void 0!==r.get?r.get.call(s):void 0:f(c=o(t))?e(c,n,s):void 0}var i=r(31),o=r(32),u=r(24),c=r(1),f=r(6),a=r(2);c(c.S,"Reflect",{get:e})},function(t,n,r){var e=r(1);e(e.S,"Reflect",{has:function(t,n){return n in t}})},function(t,n,r){var e=r(1),i=r(2),o=Object.isExtensible;e(e.S,"Reflect",{isExtensible:function(t){return i(t),!o||o(t)}})},function(t,n,r){var e=r(1);e(e.S,"Reflect",{ownKeys:r(177)})},function(t,n,r){var e=r(1),i=r(2),o=Object.preventExtensions;e(e.S,"Reflect",{preventExtensions:function(t){i(t);try{return o&&o(t),!0}catch(t){return!1}}})},function(t,n,r){var e=r(1),i=r(144);i&&e(e.S,"Reflect",{setPrototypeOf:function(t,n){i.check(t,n);try{return i.set(t,n),!0}catch(t){return!1}}})},function(t,n,r){function e(t,n,r){var f,h,v=arguments.length<4?t:arguments[3],p=o.f(s(t),n);if(!p){if(l(h=u(t)))return e(h,n,r,v);p=a(0)}return c(p,"value")?!(!1===p.writable||!l(v)||(f=o.f(v,n)||a(0),f.value=r,i.f(v,n,f),0)):void 0!==p.set&&(p.set.call(v,r),!0)}var i=r(11),o=r(31),u=r(32),c=r(24),f=r(1),a=r(66),s=r(2),l=r(6);f(f.S,"Reflect",{set:e})},function(t,n,r){var e=r(3),i=r(136),o=r(11).f,u=r(71).f,c=r(122),f=r(120),a=e.RegExp,s=a,l=a.prototype,h=/a/g,v=/a/g,p=new a(h)!==h;if(r(10)&&(!p||r(4)(function(){return v[r(7)("match")]=!1,a(h)!=h||a(v)==v||"/a/i"!=a(h,"i")}))){a=function(t,n){var r=this instanceof a,e=c(t),o=void 0===n;return!r&&e&&t.constructor===a&&o?t:i(p?new s(e&&!o?t.source:t,n):s((e=t instanceof a)?t.source:t,e&&o?f.call(t):n),r?this:l,a)};for(var d=u(s),y=0;d.length>y;)!function(t){t in a||o(a,t,{configurable:!0,get:function(){return s[t]},set:function(n){s[t]=n}})}(d[y++]);l.constructor=a,a.prototype=l,r(28)(e,"RegExp",a)}r(74)("RegExp")},function(t,n,r){r(119)("match",1,function(t,n,r){return[function(r){"use strict";var e=t(this),i=void 0==r?void 0:r[n];return void 0!==i?i.call(r,e):new RegExp(r)[n](String(e))},r]})},function(t,n,r){r(119)("replace",2,function(t,n,r){return[function(e,i){"use strict";var o=t(this),u=void 0==e?void 0:e[n];return void 0!==u?u.call(e,o,i):r.call(String(o),e,i)},r]})},function(t,n,r){r(119)("search",1,function(t,n,r){return[function(r){"use strict";var e=t(this),i=void 0==r?void 0:r[n];return void 0!==i?i.call(r,e):new RegExp(r)[n](String(e))},r]})},function(t,n,r){r(119)("split",2,function(t,n,e){"use strict";var i=r(122),o=e,u=[].push,c="split",f="length",a="lastIndex";if("c"=="abbc"[c](/(b)*/)[1]||4!="test"[c](/(?:)/,-1)[f]||2!="ab"[c](/(?:ab)*/)[f]||4!="."[c](/(.?)(.?)/)[f]||"."[c](/()()/)[f]>1||""[c](/.?/)[f]){var s=void 0===/()??/.exec("")[1];e=function(t,n){var r=String(this);if(void 0===t&&0===n)return[];if(!i(t))return o.call(r,t,n);var e,c,l,h,v,p=[],d=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),y=0,g=void 0===n?4294967295:n>>>0,b=new RegExp(t.source,d+"g");for(s||(e=new RegExp("^"+b.source+"$(?!\\s)",d));(c=b.exec(r))&&!((l=c.index+c[0][f])>y&&(p.push(r.slice(y,c.index)),!s&&c[f]>1&&c[0].replace(e,function(){for(v=1;v<arguments[f]-2;v++)void 0===arguments[v]&&(c[v]=void 0)}),c[f]>1&&c.index<r[f]&&u.apply(p,c.slice(1)),h=c[0][f],y=l,p[f]>=g));)b[a]===c.index&&b[a]++;return y===r[f]?!h&&b.test("")||p.push(""):p.push(r.slice(y)),p[f]>g?p.slice(0,g):p}}else"0"[c](void 0,0)[f]&&(e=function(t,n){return void 0===t&&0===n?[]:o.call(this,t,n)});return[function(r,i){var o=t(this),u=void 0==r?void 0:r[n];return void 0!==u?u.call(r,o,i):e.call(String(o),r,i)},e]})},function(t,n,r){"use strict";r(184);var e=r(2),i=r(120),o=r(10),u="toString",c=/./[u],f=function(t){r(28)(RegExp.prototype,u,t,!0)};r(4)(function(){return"/a/b"!=c.call({source:"a",flags:"b"})})?f(function(){var t=e(this);return"/".concat(t.source,"/","flags"in t?t.flags:!o&&t instanceof RegExp?i.call(t):void 0)}):c.name!=u&&f(function(){return c.call(this)})},function(t,n,r){"use strict";r(29)("anchor",function(t){return function(n){return t(this,"a","name",n)}})},function(t,n,r){"use strict";r(29)("big",function(t){return function(){return t(this,"big","","")}})},function(t,n,r){"use strict";r(29)("blink",function(t){return function(){return t(this,"blink","","")}})},function(t,n,r){"use strict";r(29)("bold",function(t){return function(){return t(this,"b","","")}})},function(t,n,r){"use strict";var e=r(1),i=r(147)(!1);e(e.P,"String",{codePointAt:function(t){return i(this,t)}})},function(t,n,r){"use strict";var e=r(1),i=r(16),o=r(148),u="endsWith",c=""[u];e(e.P+e.F*r(134)(u),"String",{endsWith:function(t){var n=o(this,t,u),r=arguments.length>1?arguments[1]:void 0,e=i(n.length),f=void 0===r?e:Math.min(i(r),e),a=String(t);return c?c.call(n,a,f):n.slice(f-a.length,f)===a}})},function(t,n,r){"use strict";r(29)("fixed",function(t){return function(){return t(this,"tt","","")}})},function(t,n,r){"use strict";r(29)("fontcolor",function(t){return function(n){return t(this,"font","color",n)}})},function(t,n,r){"use strict";r(29)("fontsize",function(t){return function(n){return t(this,"font","size",n)}})},function(t,n,r){var e=r(1),i=r(75),o=String.fromCharCode,u=String.fromCodePoint;e(e.S+e.F*(!!u&&1!=u.length),"String",{fromCodePoint:function(t){for(var n,r=[],e=arguments.length,u=0;e>u;){if(n=+arguments[u++],i(n,1114111)!==n)throw RangeError(n+" is not a valid code point");r.push(n<65536?o(n):o(55296+((n-=65536)>>10),n%1024+56320))}return r.join("")}})},function(t,n,r){"use strict";var e=r(1),i=r(148),o="includes";e(e.P+e.F*r(134)(o),"String",{includes:function(t){return!!~i(this,t,o).indexOf(t,arguments.length>1?arguments[1]:void 0)}})},function(t,n,r){"use strict";r(29)("italics",function(t){return function(){return t(this,"i","","")}})},function(t,n,r){"use strict";var e=r(147)(!0);r(140)(String,"String",function(t){this._t=String(t),this._i=0},function(){var t,n=this._t,r=this._i;return r>=n.length?{value:void 0,done:!0}:(t=e(n,r),this._i+=t.length,{value:t,done:!1})})},function(t,n,r){"use strict";r(29)("link",function(t){return function(n){return t(this,"a","href",n)}})},function(t,n,r){var e=r(1),i=r(30),o=r(16);e(e.S,"String",{raw:function(t){for(var n=i(t.raw),r=o(n.length),e=arguments.length,u=[],c=0;r>c;)u.push(String(n[c++])),c<e&&u.push(String(arguments[c]));return u.join("")}})},function(t,n,r){var e=r(1);e(e.P,"String",{repeat:r(149)})},function(t,n,r){"use strict";r(29)("small",function(t){return function(){return t(this,"small","","")}})},function(t,n,r){"use strict";var e=r(1),i=r(16),o=r(148),u="startsWith",c=""[u];e(e.P+e.F*r(134)(u),"String",{startsWith:function(t){var n=o(this,t,u),r=i(Math.min(arguments.length>1?arguments[1]:void 0,n.length)),e=String(t);return c?c.call(n,e,r):n.slice(r,r+e.length)===e}})},function(t,n,r){"use strict";r(29)("strike",function(t){return function(){return t(this,"strike","","")}})},function(t,n,r){"use strict";r(29)("sub",function(t){return function(){return t(this,"sub","","")}})},function(t,n,r){"use strict";r(29)("sup",function(t){return function(){return t(this,"sup","","")}})},function(t,n,r){"use strict";r(82)("trim",function(t){return function(){return t(this,3)}})},function(t,n,r){"use strict";var e=r(3),i=r(24),o=r(10),u=r(1),c=r(28),f=r(65).KEY,a=r(4),s=r(126),l=r(81),h=r(76),v=r(7),p=r(182),d=r(153),y=r(206),g=r(205),b=r(138),m=r(2),x=r(30),w=r(50),S=r(66),_=r(70),O=r(174),E=r(31),P=r(11),j=r(72),F=E.f,M=P.f,A=O.f,N=e.Symbol,T=e.JSON,I=T&&T.stringify,k="prototype",L=v("_hidden"),R=v("toPrimitive"),C={}.propertyIsEnumerable,D=s("symbol-registry"),U=s("symbols"),W=s("op-symbols"),G=Object[k],B="function"==typeof N,V=e.QObject,z=!V||!V[k]||!V[k].findChild,q=o&&a(function(){return 7!=_(M({},"a",{get:function(){return M(this,"a",{value:7}).a}})).a})?function(t,n,r){var e=F(G,n);e&&delete G[n],M(t,n,r),e&&t!==G&&M(G,n,e)}:M,K=function(t){var n=U[t]=_(N[k]);return n._k=t,n},J=B&&"symbol"==typeof N.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof N},Y=function(t,n,r){return t===G&&Y(W,n,r),m(t),n=w(n,!0),m(r),i(U,n)?(r.enumerable?(i(t,L)&&t[L][n]&&(t[L][n]=!1),r=_(r,{enumerable:S(0,!1)})):(i(t,L)||M(t,L,S(1,{})),t[L][n]=!0),q(t,n,r)):M(t,n,r)},H=function(t,n){m(t);for(var r,e=g(n=x(n)),i=0,o=e.length;o>i;)Y(t,r=e[i++],n[r]);return t},$=function(t,n){return void 0===n?_(t):H(_(t),n)},X=function(t){var n=C.call(this,t=w(t,!0));return!(this===G&&i(U,t)&&!i(W,t))&&(!(n||!i(this,t)||!i(U,t)||i(this,L)&&this[L][t])||n)},Q=function(t,n){if(t=x(t),n=w(n,!0),t!==G||!i(U,n)||i(W,n)){var r=F(t,n);return!r||!i(U,n)||i(t,L)&&t[L][n]||(r.enumerable=!0),r}},Z=function(t){for(var n,r=A(x(t)),e=[],o=0;r.length>o;)i(U,n=r[o++])||n==L||n==f||e.push(n);return e},tt=function(t){for(var n,r=t===G,e=A(r?W:x(t)),o=[],u=0;e.length>u;)!i(U,n=e[u++])||r&&!i(G,n)||o.push(U[n]);return o};B||(N=function(){if(this instanceof N)throw TypeError("Symbol is not a constructor!");var t=h(arguments.length>0?arguments[0]:void 0),n=function(r){this===G&&n.call(W,r),i(this,L)&&i(this[L],t)&&(this[L][t]=!1),q(this,t,S(1,r))};return o&&z&&q(G,t,{configurable:!0,set:n}),K(t)},c(N[k],"toString",function(){return this._k}),E.f=Q,P.f=Y,r(71).f=O.f=Z,r(116).f=X,r(125).f=tt,o&&!r(69)&&c(G,"propertyIsEnumerable",X,!0),p.f=function(t){return K(v(t))}),u(u.G+u.W+u.F*!B,{Symbol:N});for(var nt="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),rt=0;nt.length>rt;)v(nt[rt++]);for(var nt=j(v.store),rt=0;nt.length>rt;)d(nt[rt++]);u(u.S+u.F*!B,"Symbol",{for:function(t){return i(D,t+="")?D[t]:D[t]=N(t)},keyFor:function(t){if(J(t))return y(D,t);throw TypeError(t+" is not a symbol!")},useSetter:function(){z=!0},useSimple:function(){z=!1}}),u(u.S+u.F*!B,"Object",{create:$,defineProperty:Y,defineProperties:H,getOwnPropertyDescriptor:Q,getOwnPropertyNames:Z,getOwnPropertySymbols:tt}),T&&u(u.S+u.F*(!B||a(function(){var t=N();return"[null]"!=I([t])||"{}"!=I({a:t})||"{}"!=I(Object(t))})),"JSON",{stringify:function(t){if(void 0!==t&&!J(t)){for(var n,r,e=[t],i=1;arguments.length>i;)e.push(arguments[i++]);return n=e[1],"function"==typeof n&&(r=n),!r&&b(n)||(n=function(t,n){if(r&&(n=r.call(this,t,n)),!J(n))return n}),e[1]=n,I.apply(T,e)}}}),N[k][R]||r(27)(N[k],R,N[k].valueOf),l(N,"Symbol"),l(Math,"Math",!0),l(e.JSON,"JSON",!0)},function(t,n,r){"use strict";var e=r(1),i=r(127),o=r(152),u=r(2),c=r(75),f=r(16),a=r(6),s=r(3).ArrayBuffer,l=r(146),h=o.ArrayBuffer,v=o.DataView,p=i.ABV&&s.isView,d=h.prototype.slice,y=i.VIEW,g="ArrayBuffer";e(e.G+e.W+e.F*(s!==h),{ArrayBuffer:h}),e(e.S+e.F*!i.CONSTR,g,{isView:function(t){return p&&p(t)||a(t)&&y in t}}),e(e.P+e.U+e.F*r(4)(function(){return!new h(2).slice(1,void 0).byteLength}),g,{slice:function(t,n){if(void 0!==d&&void 0===n)return d.call(u(this),t);for(var r=u(this).byteLength,e=c(t,r),i=c(void 0===n?r:n,r),o=new(l(this,h))(f(i-e)),a=new v(this),s=new v(o),p=0;e<i;)s.setUint8(p++,a.getUint8(e++));return o}}),r(74)(g)},function(t,n,r){var e=r(1);e(e.G+e.W+e.F*!r(127).ABV,{DataView:r(152).DataView})},function(t,n,r){r(55)("Float32",4,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Float64",8,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Int16",2,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Int32",4,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Int8",1,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint16",2,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint32",4,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint8",1,function(t){return function(n,r,e){return t(this,n,r,e)}})},function(t,n,r){r(55)("Uint8",1,function(t){return function(n,r,e){return t(this,n,r,e)}},!0)},function(t,n,r){"use strict";var e=r(166);r(118)("WeakSet",function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return e.def(this,t,!0)}},e,!1,!0)},function(t,n,r){"use strict";var e=r(1),i=r(117)(!0);e(e.P,"Array",{includes:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0)}}),r(78)("includes")},function(t,n,r){var e=r(1),i=r(143)(),o=r(3).process,u="process"==r(45)(o);e(e.G,{asap:function(t){var n=u&&o.domain;i(n?n.bind(t):t)}})},function(t,n,r){var e=r(1),i=r(45);e(e.S,"Error",{isError:function(t){return"Error"===i(t)}})},function(t,n,r){var e=r(1);e(e.P+e.R,"Map",{toJSON:r(165)("Map")})},function(t,n,r){var e=r(1);e(e.S,"Math",{iaddh:function(t,n,r,e){var i=t>>>0,o=n>>>0,u=r>>>0;return o+(e>>>0)+((i&u|(i|u)&~(i+u>>>0))>>>31)|0}})},function(t,n,r){var e=r(1);e(e.S,"Math",{imulh:function(t,n){var r=65535,e=+t,i=+n,o=e&r,u=i&r,c=e>>16,f=i>>16,a=(c*u>>>0)+(o*u>>>16);return c*f+(a>>16)+((o*f>>>0)+(a&r)>>16)}})},function(t,n,r){var e=r(1);e(e.S,"Math",{isubh:function(t,n,r,e){var i=t>>>0,o=n>>>0,u=r>>>0;return o-(e>>>0)-((~i&u|~(i^u)&i-u>>>0)>>>31)|0}})},function(t,n,r){var e=r(1);e(e.S,"Math",{umulh:function(t,n){var r=65535,e=+t,i=+n,o=e&r,u=i&r,c=e>>>16,f=i>>>16,a=(c*u>>>0)+(o*u>>>16);return c*f+(a>>>16)+((o*f>>>0)+(a&r)>>>16)}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(26),u=r(11);r(10)&&e(e.P+r(124),"Object",{__defineGetter__:function(t,n){u.f(i(this),t,{get:o(n),enumerable:!0,configurable:!0})}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(26),u=r(11);r(10)&&e(e.P+r(124),"Object",{__defineSetter__:function(t,n){u.f(i(this),t,{set:o(n),enumerable:!0,configurable:!0})}})},function(t,n,r){var e=r(1),i=r(176)(!0);e(e.S,"Object",{entries:function(t){return i(t)}})},function(t,n,r){var e=r(1),i=r(177),o=r(30),u=r(31),c=r(131);e(e.S,"Object",{getOwnPropertyDescriptors:function(t){for(var n,r=o(t),e=u.f,f=i(r),a={},s=0;f.length>s;)c(a,n=f[s++],e(r,n));return a}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(50),u=r(32),c=r(31).f;r(10)&&e(e.P+r(124),"Object",{__lookupGetter__:function(t){var n,r=i(this),e=o(t,!0);do{if(n=c(r,e))return n.get}while(r=u(r))}})},function(t,n,r){"use strict";var e=r(1),i=r(17),o=r(50),u=r(32),c=r(31).f;r(10)&&e(e.P+r(124),"Object",{__lookupSetter__:function(t){var n,r=i(this),e=o(t,!0);do{if(n=c(r,e))return n.set}while(r=u(r))}})},function(t,n,r){var e=r(1),i=r(176)(!1);e(e.S,"Object",{values:function(t){return i(t)}})},function(t,n,r){"use strict";var e=r(1),i=r(3),o=r(52),u=r(143)(),c=r(7)("observable"),f=r(26),a=r(2),s=r(68),l=r(73),h=r(27),v=r(79),p=v.RETURN,d=function(t){return null==t?void 0:f(t)},y=function(t){var n=t._c;n&&(t._c=void 0,n())},g=function(t){return void 0===t._o},b=function(t){g(t)||(t._o=void 0,y(t))},m=function(t,n){a(t),this._c=void 0,this._o=t,t=new x(this);try{var r=n(t),e=r;null!=r&&("function"==typeof r.unsubscribe?r=function(){e.unsubscribe()}:f(r),this._c=r)}catch(n){return void t.error(n)}g(this)&&y(this)};m.prototype=l({},{unsubscribe:function(){b(this)}});var x=function(t){this._s=t};x.prototype=l({},{next:function(t){var n=this._s;if(!g(n)){var r=n._o;try{var e=d(r.next);if(e)return e.call(r,t)}catch(t){try{b(n)}finally{throw t}}}},error:function(t){var n=this._s;if(g(n))throw t;var r=n._o;n._o=void 0;try{var e=d(r.error);if(!e)throw t;t=e.call(r,t)}catch(t){try{y(n)}finally{throw t}}return y(n),t},complete:function(t){var n=this._s;if(!g(n)){var r=n._o;n._o=void 0;try{var e=d(r.complete);t=e?e.call(r,t):void 0}catch(t){try{y(n)}finally{throw t}}return y(n),t}}});var w=function(t){s(this,w,"Observable","_f")._f=f(t)};l(w.prototype,{subscribe:function(t){return new m(t,this._f)},forEach:function(t){var n=this;return new(o.Promise||i.Promise)(function(r,e){f(t);var i=n.subscribe({next:function(n){try{return t(n)}catch(t){e(t),i.unsubscribe()}},error:e,complete:r})})}}),l(w,{from:function(t){var n="function"==typeof this?this:w,r=d(a(t)[c]);if(r){var e=a(r.call(t));return e.constructor===n?e:new n(function(t){return e.subscribe(t)})}return new n(function(n){var r=!1;return u(function(){if(!r){try{if(v(t,!1,function(t){if(n.next(t),r)return p})===p)return}catch(t){if(r)throw t;return void n.error(t)}n.complete()}}),function(){r=!0}})},of:function(){for(var t=0,n=arguments.length,r=Array(n);t<n;)r[t]=arguments[t++];return new("function"==typeof this?this:w)(function(t){var n=!1;return u(function(){if(!n){for(var e=0;e<r.length;++e)if(t.next(r[e]),n)return;t.complete()}}),function(){n=!0}})}}),h(w.prototype,c,function(){return this}),e(e.G,{Observable:w}),r(74)("Observable")},function(t,n,r){var e=r(54),i=r(2),o=e.key,u=e.set;e.exp({defineMetadata:function(t,n,r,e){u(t,n,i(r),o(e))}})},function(t,n,r){var e=r(54),i=r(2),o=e.key,u=e.map,c=e.store;e.exp({deleteMetadata:function(t,n){var r=arguments.length<3?void 0:o(arguments[2]),e=u(i(n),r,!1);if(void 0===e||!e.delete(t))return!1;if(e.size)return!0;var f=c.get(n);return f.delete(r),!!f.size||c.delete(n)}})},function(t,n,r){var e=r(185),i=r(161),o=r(54),u=r(2),c=r(32),f=o.keys,a=o.key,s=function(t,n){var r=f(t,n),o=c(t);if(null===o)return r;var u=s(o,n);return u.length?r.length?i(new e(r.concat(u))):u:r};o.exp({getMetadataKeys:function(t){return s(u(t),arguments.length<2?void 0:a(arguments[1]))}})},function(t,n,r){var e=r(54),i=r(2),o=r(32),u=e.has,c=e.get,f=e.key,a=function(t,n,r){if(u(t,n,r))return c(t,n,r);var e=o(n);return null!==e?a(t,e,r):void 0};e.exp({getMetadata:function(t,n){return a(t,i(n),arguments.length<3?void 0:f(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=e.keys,u=e.key;e.exp({getOwnMetadataKeys:function(t){
return o(i(t),arguments.length<2?void 0:u(arguments[1]))}})},function(t,n,r){var e=r(54),i=r(2),o=e.get,u=e.key;e.exp({getOwnMetadata:function(t,n){return o(t,i(n),arguments.length<3?void 0:u(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=r(32),u=e.has,c=e.key,f=function(t,n,r){if(u(t,n,r))return!0;var e=o(n);return null!==e&&f(t,e,r)};e.exp({hasMetadata:function(t,n){return f(t,i(n),arguments.length<3?void 0:c(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=e.has,u=e.key;e.exp({hasOwnMetadata:function(t,n){return o(t,i(n),arguments.length<3?void 0:u(arguments[2]))}})},function(t,n,r){var e=r(54),i=r(2),o=r(26),u=e.key,c=e.set;e.exp({metadata:function(t,n){return function(r,e){c(t,n,(void 0!==e?i:o)(r),u(e))}}})},function(t,n,r){var e=r(1);e(e.P+e.R,"Set",{toJSON:r(165)("Set")})},function(t,n,r){"use strict";var e=r(1),i=r(147)(!0);e(e.P,"String",{at:function(t){return i(this,t)}})},function(t,n,r){"use strict";var e=r(1),i=r(46),o=r(16),u=r(122),c=r(120),f=RegExp.prototype,a=function(t,n){this._r=t,this._s=n};r(139)(a,"RegExp String",function(){var t=this._r.exec(this._s);return{value:t,done:null===t}}),e(e.P,"String",{matchAll:function(t){if(i(this),!u(t))throw TypeError(t+" is not a regexp!");var n=String(this),r="flags"in f?String(t.flags):c.call(t),e=new RegExp(t.source,~r.indexOf("g")?r:"g"+r);return e.lastIndex=o(t.lastIndex),new a(e,n)}})},function(t,n,r){"use strict";var e=r(1),i=r(181);e(e.P,"String",{padEnd:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0,!1)}})},function(t,n,r){"use strict";var e=r(1),i=r(181);e(e.P,"String",{padStart:function(t){return i(this,t,arguments.length>1?arguments[1]:void 0,!0)}})},function(t,n,r){"use strict";r(82)("trimLeft",function(t){return function(){return t(this,1)}},"trimStart")},function(t,n,r){"use strict";r(82)("trimRight",function(t){return function(){return t(this,2)}},"trimEnd")},function(t,n,r){r(153)("asyncIterator")},function(t,n,r){r(153)("observable")},function(t,n,r){var e=r(1);e(e.S,"System",{global:r(3)})},function(t,n,r){for(var e=r(155),i=r(28),o=r(3),u=r(27),c=r(80),f=r(7),a=f("iterator"),s=f("toStringTag"),l=c.Array,h=["NodeList","DOMTokenList","MediaList","StyleSheetList","CSSRuleList"],v=0;v<5;v++){var p,d=h[v],y=o[d],g=y&&y.prototype;if(g){g[a]||u(g,a,l),g[s]||u(g,s,d),c[d]=l;for(p in e)g[p]||i(g,p,e[p],!0)}}},function(t,n,r){var e=r(1),i=r(151);e(e.G+e.B,{setImmediate:i.set,clearImmediate:i.clear})},function(t,n,r){var e=r(3),i=r(1),o=r(121),u=r(207),c=e.navigator,f=!!c&&/MSIE .\./.test(c.userAgent),a=function(t){return f?function(n,r){return t(o(u,[].slice.call(arguments,2),"function"==typeof n?n:Function(n)),r)}:t};i(i.G+i.B+i.F*f,{setTimeout:a(e.setTimeout),setInterval:a(e.setInterval)})},function(t,n,r){r(330),r(269),r(271),r(270),r(273),r(275),r(280),r(274),r(272),r(282),r(281),r(277),r(278),r(276),r(268),r(279),r(283),r(284),r(236),r(238),r(237),r(286),r(285),r(256),r(266),r(267),r(257),r(258),r(259),r(260),r(261),r(262),r(263),r(264),r(265),r(239),r(240),r(241),r(242),r(243),r(244),r(245),r(246),r(247),r(248),r(249),r(250),r(251),r(252),r(253),r(254),r(255),r(317),r(322),r(329),r(320),r(312),r(313),r(318),r(323),r(325),r(308),r(309),r(310),r(311),r(314),r(315),r(316),r(319),r(321),r(324),r(326),r(327),r(328),r(231),r(233),r(232),r(235),r(234),r(220),r(218),r(224),r(221),r(227),r(229),r(217),r(223),r(214),r(228),r(212),r(226),r(225),r(219),r(222),r(211),r(213),r(216),r(215),r(230),r(155),r(302),r(307),r(184),r(303),r(304),r(305),r(306),r(287),r(183),r(185),r(186),r(342),r(331),r(332),r(337),r(340),r(341),r(335),r(338),r(336),r(339),r(333),r(334),r(288),r(289),r(290),r(291),r(292),r(295),r(293),r(294),r(296),r(297),r(298),r(299),r(301),r(300),r(343),r(369),r(372),r(371),r(373),r(374),r(370),r(375),r(376),r(354),r(357),r(353),r(351),r(352),r(355),r(356),r(346),r(368),r(377),r(345),r(347),r(349),r(348),r(350),r(359),r(360),r(362),r(361),r(364),r(363),r(365),r(366),r(367),r(344),r(358),r(380),r(379),r(378),t.exports=r(52)},function(t,n){function r(t,n){if("string"==typeof n)return t.insertAdjacentHTML("afterend",n);var r=t.nextSibling;return r?t.parentNode.insertBefore(n,r):t.parentNode.appendChild(n)}t.exports=r},,,,,,,,,function(t,n,r){(function(n,r){!function(n){"use strict";function e(t,n,r,e){var i=n&&n.prototype instanceof o?n:o,u=Object.create(i.prototype),c=new p(e||[]);return u._invoke=s(t,r,c),u}function i(t,n,r){try{return{type:"normal",arg:t.call(n,r)}}catch(t){return{type:"throw",arg:t}}}function o(){}function u(){}function c(){}function f(t){["next","throw","return"].forEach(function(n){t[n]=function(t){return this._invoke(n,t)}})}function a(t){function n(r,e,o,u){var c=i(t[r],t,e);if("throw"!==c.type){var f=c.arg,a=f.value;return a&&"object"==typeof a&&m.call(a,"__await")?Promise.resolve(a.__await).then(function(t){n("next",t,o,u)},function(t){n("throw",t,o,u)}):Promise.resolve(a).then(function(t){f.value=t,o(f)},u)}u(c.arg)}function e(t,r){function e(){return new Promise(function(e,i){n(t,r,e,i)})}return o=o?o.then(e,e):e()}"object"==typeof r&&r.domain&&(n=r.domain.bind(n));var o;this._invoke=e}function s(t,n,r){var e=P;return function(o,u){if(e===F)throw new Error("Generator is already running");if(e===M){if("throw"===o)throw u;return y()}for(r.method=o,r.arg=u;;){var c=r.delegate;if(c){var f=l(c,r);if(f){if(f===A)continue;return f}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(e===P)throw e=M,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);e=F;var a=i(t,n,r);if("normal"===a.type){if(e=r.done?M:j,a.arg===A)continue;return{value:a.arg,done:r.done}}"throw"===a.type&&(e=M,r.method="throw",r.arg=a.arg)}}}function l(t,n){var r=t.iterator[n.method];if(r===g){if(n.delegate=null,"throw"===n.method){if(t.iterator.return&&(n.method="return",n.arg=g,l(t,n),"throw"===n.method))return A;n.method="throw",n.arg=new TypeError("The iterator does not provide a 'throw' method")}return A}var e=i(r,t.iterator,n.arg);if("throw"===e.type)return n.method="throw",n.arg=e.arg,n.delegate=null,A;var o=e.arg;return o?o.done?(n[t.resultName]=o.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=g),n.delegate=null,A):o:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,A)}function h(t){var n={tryLoc:t[0]};1 in t&&(n.catchLoc=t[1]),2 in t&&(n.finallyLoc=t[2],n.afterLoc=t[3]),this.tryEntries.push(n)}function v(t){var n=t.completion||{};n.type="normal",delete n.arg,t.completion=n}function p(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(h,this),this.reset(!0)}function d(t){if(t){var n=t[w];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,e=function n(){for(;++r<t.length;)if(m.call(t,r))return n.value=t[r],n.done=!1,n;return n.value=g,n.done=!0,n};return e.next=e}}return{next:y}}function y(){return{value:g,done:!0}}var g,b=Object.prototype,m=b.hasOwnProperty,x="function"==typeof Symbol?Symbol:{},w=x.iterator||"@@iterator",S=x.asyncIterator||"@@asyncIterator",_=x.toStringTag||"@@toStringTag",O="object"==typeof t,E=n.regeneratorRuntime;if(E)return void(O&&(t.exports=E));E=n.regeneratorRuntime=O?t.exports:{},E.wrap=e;var P="suspendedStart",j="suspendedYield",F="executing",M="completed",A={},N={};N[w]=function(){return this};var T=Object.getPrototypeOf,I=T&&T(T(d([])));I&&I!==b&&m.call(I,w)&&(N=I);var k=c.prototype=o.prototype=Object.create(N);u.prototype=k.constructor=c,c.constructor=u,c[_]=u.displayName="GeneratorFunction",E.isGeneratorFunction=function(t){var n="function"==typeof t&&t.constructor;return!!n&&(n===u||"GeneratorFunction"===(n.displayName||n.name))},E.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,c):(t.__proto__=c,_ in t||(t[_]="GeneratorFunction")),t.prototype=Object.create(k),t},E.awrap=function(t){return{__await:t}},f(a.prototype),a.prototype[S]=function(){return this},E.AsyncIterator=a,E.async=function(t,n,r,i){var o=new a(e(t,n,r,i));return E.isGeneratorFunction(n)?o:o.next().then(function(t){return t.done?t.value:o.next()})},f(k),k[_]="Generator",k.toString=function(){return"[object Generator]"},E.keys=function(t){var n=[];for(var r in t)n.push(r);return n.reverse(),function r(){for(;n.length;){var e=n.pop();if(e in t)return r.value=e,r.done=!1,r}return r.done=!0,r}},E.values=d,p.prototype={constructor:p,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=g,this.done=!1,this.delegate=null,this.method="next",this.arg=g,this.tryEntries.forEach(v),!t)for(var n in this)"t"===n.charAt(0)&&m.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=g)},stop:function(){this.done=!0;var t=this.tryEntries[0],n=t.completion;if("throw"===n.type)throw n.arg;return this.rval},dispatchException:function(t){function n(n,e){return o.type="throw",o.arg=t,r.next=n,e&&(r.method="next",r.arg=g),!!e}if(this.done)throw t;for(var r=this,e=this.tryEntries.length-1;e>=0;--e){var i=this.tryEntries[e],o=i.completion;if("root"===i.tryLoc)return n("end");if(i.tryLoc<=this.prev){var u=m.call(i,"catchLoc"),c=m.call(i,"finallyLoc");if(u&&c){if(this.prev<i.catchLoc)return n(i.catchLoc,!0);if(this.prev<i.finallyLoc)return n(i.finallyLoc)}else if(u){if(this.prev<i.catchLoc)return n(i.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return n(i.finallyLoc)}}}},abrupt:function(t,n){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc<=this.prev&&m.call(e,"finallyLoc")&&this.prev<e.finallyLoc){var i=e;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=n&&n<=i.finallyLoc&&(i=null);var o=i?i.completion:{};return o.type=t,o.arg=n,i?(this.method="next",this.next=i.finallyLoc,A):this.complete(o)},complete:function(t,n){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&n&&(this.next=n),A},finish:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),v(r),A}},catch:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc===t){var e=r.completion;if("throw"===e.type){var i=e.arg;v(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:d(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=g),A}}}("object"==typeof n?n:"object"==typeof window?window:"object"==typeof self?self:this)}).call(n,function(){return this}(),r(158))}])</script><script src="/./main.0cf68a.js"></script><script>!function(){!function(e){var t=document.createElement("script");document.getElementsByTagName("body")[0].appendChild(t),t.setAttribute("src",e)}("/slider.e37972.js")}()</script>



<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    
<div class="tools-col" q-class="show:isShow,hide:isShow|isFalse" q-on="click:stop(e)">
  <div class="tools-nav header-menu">
    
    
      
      
      
    
      
      
      
    
      
      
      
    
    

    <ul style="width: 70%">
    
    
      
      <li style="width: 33.333333333333336%" q-on="click: openSlider(e, 'innerArchive')"><a href="javascript:void(0)" q-class="active:innerArchive">所有文章</a></li>
      
        
      
      <li style="width: 33.333333333333336%" q-on="click: openSlider(e, 'friends')"><a href="javascript:void(0)" q-class="active:friends">友链</a></li>
      
        
      
      <li style="width: 33.333333333333336%" q-on="click: openSlider(e, 'aboutme')"><a href="javascript:void(0)" q-class="active:aboutme">关于我</a></li>
      
        
    </ul>
  </div>
  <div class="tools-wrap">
    
    	<section class="tools-section tools-section-all" q-show="innerArchive">
        <div class="search-wrap">
          <input class="search-ipt" q-model="search" type="text" placeholder="find something…">
          <i class="icon-search icon" q-show="search|isEmptyStr"></i>
          <i class="icon-close icon" q-show="search|isNotEmptyStr" q-on="click:clearChose(e)"></i>
        </div>
        <div class="widget tagcloud search-tag">
          <p class="search-tag-wording">tag:</p>
          <label class="search-switch">
            <input type="checkbox" q-on="click:toggleTag(e)" q-attr="checked:showTags">
          </label>
          <ul class="article-tag-list" q-show="showTags">
             
              <li class="article-tag-list-item">
                <a href="javascript:void(0)" class="js-tag color3">随笔</a>
              </li>
            
            <div class="clearfix"></div>
          </ul>
        </div>
        <ul class="search-ul">
          <p q-show="jsonFail" style="padding: 20px; font-size: 12px;">
            缺失模块。<br/>1、请确保node版本大于6.2<br/>2、在博客根目录（注意不是yilia根目录）执行以下命令：<br/> npm i hexo-generator-json-content --save<br/><br/>
            3、在根目录_config.yml里添加配置：
<pre style="font-size: 12px;" q-show="jsonFail">
  jsonContent:
    meta: false
    pages: false
    posts:
      title: true
      date: true
      path: true
      text: false
      raw: false
      content: false
      slug: false
      updated: false
      comments: false
      link: false
      permalink: false
      excerpt: false
      categories: false
      tags: true
</pre>
          </p>
          <li class="search-li" q-repeat="items" q-show="isShow">
            <a q-attr="href:path|urlformat" class="search-title"><i class="icon-quo-left icon"></i><span q-text="title"></span></a>
            <p class="search-time">
              <i class="icon-calendar icon"></i>
              <span q-text="date|dateformat"></span>
            </p>
            <p class="search-tag">
              <i class="icon-price-tags icon"></i>
              <span q-repeat="tags" q-on="click:choseTag(e, name)" q-text="name|tagformat"></span>
            </p>
          </li>
        </ul>
    	</section>
    

    
    	<section class="tools-section tools-section-friends" q-show="friends">
  		
        <ul class="search-ul">
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接1</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接2</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接3</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接4</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接5</a>
            </li>
          
            <li class="search-li">
              <a href="http://localhost:4000/" target="_blank" class="search-title"><i class="icon-quo-left icon"></i>友情链接6</a>
            </li>
          
        </ul>
  		
    	</section>
    

    
    	<section class="tools-section tools-section-me" q-show="aboutme">
  	  	
  	  		<div class="aboutme-wrap">
				<div style="display:;">
					<script type="text/javascript" src="https://api.lwl12.com/hitokoto/v1?encode=js&charset=utf-8"></script>
					<p style="margin:0 20px 0 20px;">
						<span id="lwlhitokoto">
							<script>
								lwlhitokoto();
							</script>
						</span>
					</p>
					<p id="js-aboutme" style="margin:0 20px 0 20px;">很惭愧&lt;br&gt;&lt;br&gt;只做了一点微小的工作&lt;br&gt;谢谢大家</P>
				</div>
			</div>
  	  	
    	</section>
    
  </div>
  
</div>
    <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>
  </div>
</body>
</html>